What is the best way to connect to node.js API's GET method from component

Viewed 18

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...

0 Answers
Related