I am still relatively new to node.js and I am wondering what the best way to call my API's GET method from within this next.js component. So far I have my DemoForm.js component here:
import { useState } from 'react'
import { useRouter } from 'next/router'
import { mutate } from 'swr'
const DemoForm = ({ req, formId, demoForm, forNewDemo = true }) => {
const router = useRouter()
const contentType = 'application/json'
const [errors, setErrors] = useState({})
const [message, setMessage] = useState('')
const [demoName, setDemoName] = useState(demoForm.demoName || 'demo name')
const [response, setResponse] = useState (null)
const makeRequest = async () => {
const res = await fetch('api/demos')
setResponse({
status: res.status,
body: await res.json(),
limit: res.headers.get('X-RateLimit-Limit'),
remaining: res.headers.get('X-RateLimit-Remaining'),
})
}
const [form, setForm] = useState({
demo_token: demoForm.demo_token,
demo_name: demoForm.demo_name,
})
/* The PUT method edits an existing entry in the mongodb database. */
const putData = async (form) => {
const { id } = router.query
try {
const res = await fetch(`/api/demos/${id}`, {
method: 'PUT',
headers: {
Accept: contentType,
'Content-Type': contentType,
},
body: JSON.stringify(form),
})
// Throw error with status code in case Fetch API req failed
if (!res.ok) {
throw new Error(res.status)
}
const { data } = await res.json()
mutate(`/api/demos/${id}`, data, false) // Update the local data without a revalidation
router.push('/')
} catch (error) {
setMessage('Failed to update')
}
}
/* The POST method adds a new entry in the mongodb database. */
const postData = async (form) => {
try {
const res = await fetch('/api/demos', {
method: 'POST',
headers: {
Accept: contentType,
'Content-Type': contentType,
},
body: JSON.stringify(form),
})
// Throw error with status code in case Fetch API req failed
if (!res.ok) {
throw new Error(res.status)
}
router.push('/')
} catch (error) {
setMessage('Failed to add new function')
}
}
const handleChange = (e) => {
const target = e.target
const value =
target.name === 'demo_token' ? target.checked : target.value
const name = target.name
setForm({
...form,
[name]: value,
})
}
/* Makes sure demo info is filled for demo name, owner name, species, and image url*/
const formValidate = () => {
let err = {}
// if (!form.demo_token) err.demo_token = 'Checkbox selection required'
if (!form.demo_name) err.demo_name = 'Name is required'
return err
}
const handleSubmit = (e) => {
e.preventDefault()
const errs = formValidate()
if (Object.keys(errs).length === 0) {
forNewDemo ? postData(form) : putData(form)
} else {
setErrors({ errs })
}
}
return (
<>
<form id={formId} onSubmit={handleSubmit}>
<span className="flex flex-row justify-center">
<label htmlFor="demo_name">Name</label>
<input
name="demo_name"
value={form.demo_name}
onChange={handleChange}
/>
<br />
</span>
<span className="flex flex-row justify-center">
<label htmlFor="demo_token">Pro?</label>
<input
type="checkbox"
name="demo_token"
checked={form.demo_token}
onChange={handleChange}
/>
<br />
</span>
<span className="flex flex-row justify-center">
<button type="submit" className=" bg-gray-800 btn-sm text-teal-200 hover:text-teal-300 flex-row justify-start pl-4" onClick={() => makeRequest()}>Make Request</button>
{/* {response && (
<code>
<pre>{JSON.stringify(response, null, 2)}</pre>
</code>
)} */}
</span>
<p>{message}</p>
<div>
{Object.keys(errors).map((err, index) => (
<li key={index}>{err}</li>
))}
</div>
</form>
</>
)
}
export default DemoForm
and here is the API
pages/api/demos/[id].js
import dbConnect from '../../../lib/dbConnect'
import Demo from '../../../models/Demo'
export default async function handler(req, res) {
const {
query: { id },
method,
} = req
await dbConnect()
switch (method) {
case 'GET' /* Get a model by its ID */:
try {
const demo = await Demo.findById(id)
if (!demo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'PUT' /* Edit a model by its ID */:
try {
const demo = await Demo.findByIdAndUpdate(id, req.body, {
new: true,
runValidators: true,
})
if (!demo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'DELETE' /* Delete a model by its ID */:
try {
const deletedDemo = await Demo.deleteOne({ _id: id })
if (!deletedDemo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: {} })
} catch (error) {
res.status(400).json({ success: false })
}
break
default:
res.status(400).json({ success: false })
break
}
}
pages/api/demos/index.js
import dbConnect from '../../../lib/dbConnect'
import Demo from '../../../models/Demo'
import fs from 'fs'
const shell = require('shelljs');
export default async function handler(req, res) {
const {
method,
body,
} = req
await dbConnect()
switch (method) {
case 'GET':
try {
const demos = await Demo.find({}) /* find all the data in our database */
res.status(200).json({ success: true, data: demos })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'POST':
try {
const demo = await Demo .create(
req.body
) /* create a new model in the database */
res.status(201).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
default:
res.status(400).json({ success: false })
break
}
}
The form is setup to work with my API's post and put methods, however, I am needing to call the GET method to essentially map out all of the demos by there ${id} so they can be rendered on screen. I am having a tough time doing this from within my Next.js component. ANY help would be greatly appreciated! Thanks y'all...