Here, we learn how to create APIs and crud operation in the next.js.
First, open the next.js application in the code editor.
Then install mongoose and mongodb for database connection and react-bootstrap and bootstrap for styling component.
BackEnd Part:-
For DB connection create the config folder and inside that create the db.js file, then write the below code in that.
import mongoose from "mongoose"; const connection = {}; async function dbConnect() { if (connection.isConnected) { return; } const db = await mongoose.connect(process.env.databaseURL, { useNewUrlParser: true, useUnifiedTopology: true, }); connection.isConnected = db.connections[0].readyState; } export default dbConnect;
Then create a model in that database, for that create the model folder, and inside that create the student.js file, then write the below code in that.
"use strict"; const mongoose = require("mongoose"); const studentSchema = new mongoose.Schema( { firstName: { type: String, default: "", trim: true, required: true, }, lastName: { type: String, default: "", trim: true, required: true, }, age: { type: Number, trim: true, required: true, }, email: { type: String, default: "", trim: true, required: true, }, phoneNumber: { type: Number, trim: true, required: true, }, city: { type: String, default: "", trim: true, required: true, }, password: { type: String, default: "", trim: true, required: true, } }, { timestamps: true, } ); module.exports = mongoose.models.students || mongoose.model("students", studentSchema);
Now, to create APIs we need to create a student folder inside pages>api.
Then create different js files for get-all, add, get-by-id, delete and update data.
And our files look like this,
get-all.js:-
import dbConnect from "../../../config/db"; import student from "../../../models/student"; const STUDENT = student; dbConnect(); export default async (req, res) => { const { method } = req; switch (method) { case "GET": try { const studentData = await STUDENT.find({}); if (!studentData) { res.status(400).json({ isSuccess: false, message: "Failed!", }); } else { res.status(200).json({ isSuccess: true, data: studentData, }); } } catch (error) { res.status(400).json({ isSuccess: false, message: error, }); } break; default: res.status(400).json({ isSuccess: false, message: "Error", }); break; } };
add.js:-
... switch (method) { case "POST": try { const studentData = await STUDENT.create(req.body); if (!studentData) { res.status(400).json({ isSuccess: true, message: "Failed", }); } else { res.status(201).json({ isSuccess: true, message: "Success", }); } } catch (error) { res.status(400).json({ isSuccess: false, message: error, }); } break; ...
get-by-id.js:-
... switch (method) { case "GET": try { const studentData = await STUDENT.findById({ _id: req.query.id }); if (!studentData) { res.status(400).json({ isSuccess: false, message: "Data not found!", }); } else { res.status(200).json({ isSuccess: true, data: studentData, }); } } catch (error) { res.status(400).json({ isSuccess: false, message: error, }); } break; ...
delete.js:-
... switch (method) { case "DELETE": try { const studentData = await STUDENT.deleteOne({ _id: req.query.id }); if (!studentData) { res.status(400).json({ isSuccess: false, message: "Data not found!", }); } else { res.status(202).json({ isSuccess: true, message: "Success", }); } } catch (error) { res.status(400).json({ isSuccess: false, message: error, }); } break; ...
update.js:-
... switch (method) { case "POST": try { const studentData = await STUDENT.findByIdAndUpdate( { _id: req.body._id }, req.body, { new: true, } ); if (!studentData) { res.status(400).json({ isSuccess: false, message: "Data not found!", }); } else { res.status(202).json({ isSuccess: true, message: "Success", }); } } catch (error) { res.status(400).json({ isSuccess: false, message: error, }); } break; ...
Now, use these APIs to create a studentApi.js file inside axios>sevices and create URLs.
import axios from "axios"; const baseUrl = process.env.API_URL const getAllData = () => { return axios.get(baseUrl + "/get-all"); }; const addData = (data) => { return axios.post(baseUrl + "/add", data); }; const deleteData = (id) => { return axios.delete(baseUrl + `/delete?id=${id}`); }; const getByIdData = (id) => { return axios.get(baseUrl + `/get-by-id?id=${id}`); }; const updateData = (data) => { return axios.post(baseUrl + "/update", data); }; export { getAllData, addData, deleteData, getByIdData, updateData }
FrontEnd Part:-
First create Data.jsx file inside the pages folder, to show the table.
Here call get-all data API and set this in useState and show using the map function.
import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { Button, Container, Row, Table } from 'react-bootstrap' import { getAllData } from '../axios/services/studentApi' const Data = () => { const router = useRouter() const [allData, setAllData] = useState([]) const getData = () => { getAllData() .then(res => setAllData(res.data.data)) .catch(error => console.log('error', error)) } useEffect(() => { getData() }, []) return ( <div> <Container> <Row> <Table bordered hover> <thead> <tr> <th>Count</th> <th>Id</th> <th>First Name</th> <th>Last Name</th> <th>Age</th> <th>Email</th> <th>Phone Number</th> <th>City</th> <th>Action</th> </tr> </thead> <tbody> {allData.map((e, i) => { return ( <tr key={i}> <td>{e._id}</td> <td>{e.firstName}</td> <td>{e.lastName}</td> <td>{e.age}</td> <td>{e.email}</td> <td>{e.phoneNumber}</td> <td>{e.city}</td> <td> <Button variant="outline-info" onClick={() => editApiData(e._id)} className='mx-2'>Edit</Button> <Button variant="outline-danger" onClick={() => deleteApiData(e._id)}>Delete</Button> </td> </tr> ) })} </tbody> </Table> </Row> </Container> </div> ) } export default Data
Now, create add button on this page and create a form.js file inside the pages folder and also create a form in the form.js file.
//In Data.jsx file <Button variant="outline-success" onClick={() => router.push('/form')}><strong>+</strong> Add Data</Button> //In form.js file import { useRouter } from 'next/router' import { useEffect, useState } from "react" import { Button, Col, Container, Form, Row } from "react-bootstrap" import { addData } from "../axios/services/studentApi" const form = () => { const router = useRouter() const { query: { id } } = router const [dataObject, setDataObject] = useState({ firstName: '', lastName: '', email: '', password: '', age: '', phoneNumber: '', city: '' }) const inputChange = (e) => { setDataObject({ ...dataObject, [e.target.name]: e.target.value }) } const dataSubmit = (e) => { e.preventDefault() addData(dataObject) .then(res => { if (res.data.isSuccess) { router.push('/') } else { alert(res.data.message) } }) .catch(error => console.log('error', error)) } return ( <> <div className='backgroundImage' style={{ height: '100vh' }}> <Container className='d-flex justify-content-center pt-4'> <Form onSubmit={dataSubmit} className='w-75 p-3 formboader'> <Row className="mb-3"> <Form.Group as={Col} controlId="firstName"> <Form.Label>First Name</Form.Label> <Form.Control type="text" name='firstName' value={dataObject.firstName} onChange={inputChange} placeholder="Enter first name" /> </Form.Group> <Form.Group as={Col} controlId="lastName"> <Form.Label>Last Name</Form.Label> <Form.Control type="text" name='lastName' value={dataObject.lastName} onChange={inputChange} placeholder="Enter last name" /> </Form.Group> </Row> <Row className="mb-3"> <Form.Group as={Col} controlId="email"> <Form.Label>Email</Form.Label> <Form.Control type="email" name='email' value={dataObject.email} onChange={inputChange} placeholder="Enter email" /> </Form.Group> <Form.Group as={Col} controlId="password"> <Form.Label>Password</Form.Label> <Form.Control type="password" name='password' value={dataObject.password} onChange={inputChange} placeholder="Enter password" /> </Form.Group> </Row> <Row className="mb-3"> <Form.Group as={Col} controlId="age"> <Form.Label>Age</Form.Label> <Form.Control type="number" name='age' value={dataObject.age} onChange={inputChange} placeholder="Enter age" /> </Form.Group> <Form.Group as={Col} controlId="phoneNumber"> <Form.Label>Phone Number</Form.Label> <Form.Control type="number" name='phoneNumber' value={dataObject.phoneNumber} onChange={inputChange} placeholder="Enter phone number" /> </Form.Group> <Form.Group as={Col} controlId="city"> <Form.Label>City</Form.Label> <Form.Control type="text" name='city' value={dataObject.city} onChange={inputChange} placeholder="Enter city" /> </Form.Group> </Row> <Button className="btncss" type="submit"> Submit </Button> </Form> </Container> </div> </> ) } export default form
To delete data we create a function in Data.jsx file on click event.
const deleteApiData = (id) => { const isconfirm = window.confirm(`Are you sure you want to delete ${id} data?`); if (isconfirm) { deleteData(id) .then(res => { console.log(res.data) getData() }) .catch(error => console.log('error', error)) } } //html <Button variant="outline-danger" onClick={() => deleteApiData(e._id)}>Delete</Button>
To edit data,
//In Data.jsx file const editApiData = (id) => { console.log(id) router.push({ pathname: "/form", query: { id: id }, }) } <Button variant="outline-info" onClick={() => editApiData(e._id)} className='mx-2'>Edit</Button> //In form.js file ... let editID = 0 useEffect(() => { console.log('id', id) // axios.get(baseURl + `/get-by-id?id=${id}`) getByIdData(id) .then(res => { console.log(res.data) setDataObject({ ...res.data.data, id }); editID = id }) .catch(error => console.log('error', error)) }, [id]) const dataSubmit = (e) => { e.preventDefault() if (editID) { updateData(dataObject) .then(res => { if (res.data.isSuccess) { router.push('/') } else { alert(res.data.message) } editID = 0 }) .catch(error => console.log('error', error)) } else { // add data function or api call } } ......
Output:-