Next.js CRUD tutorial with examples in details
- Get link
- X
- Other Apps
Next.js CRUD tutorial with examples in details
Creating a CRUD (Create, Read, Update, Delete) application using Next.js involves several steps. In this tutorial, we will build a simple application that manages a list of items. We will use a JSON file as our data source for simplicity, but in a real-world application, you would typically connect to a database.
Prerequisites
- Basic understanding of React and Next.js
- Node.js and npm installed on your machine
Setting Up the Next.js Project
Create a new Next.js project:
bash1npx create-next-app@latest nextjs-crud-example 2cd nextjs-crud-example
Install necessary packages:
For this tutorial, we will use
axios
for making HTTP requests.bash1npm install axios
Project Structure
Here's a basic structure we'll follow:
1/nextjs-crud-example 2 ├── /pages 3 │ ├── index.js 4 │ ├── create.js 5 │ ├── edit/[id].js 6 ├── /data 7 │ └── items.json
Step 1: Create Sample Data
Create a folder named data
in the root of your project and add a file named items.json
with the following content:
json1[ 2 { "id": 1, "name": "Item 1" }, 3 { "id": 2, "name": "Item 2" }, 4 { "id": 3, "name": "Item 3" } 5]
Step 2: Create the Home Page (Read)
Edit the pages/index.js
file to read and display the items:
javascript1// pages/index.js 2import Link from 'next/link'; 3import axios from 'axios'; 4import { useEffect, useState } from 'react'; 5 6const Home = () => { 7 const [items, setItems] = useState([]); 8 9 useEffect(() => { 10 const fetchItems = async () => { 11 const response = await axios.get('/data/items.json'); 12 setItems(response.data); 13 }; 14 fetchItems(); 15 }, []); 16 17 return ( 18 <div> 19 <h1>Items List</h1> 20 <Link href="/create">Create New Item</Link> 21 <ul> 22 {items.map(item => ( 23 <li key={item.id}> 24 {item.name} - <Link href={`/edit/${item.id}`}>Edit</Link> 25 </li> 26 ))} 27 </ul> 28 </div> 29 ); 30}; 31 32export default Home;
Step 3: Create a Page to Add New Items (Create)
Create a new file named create.js
in the pages
directory:
javascript1// pages/create.js 2import { useState } from 'react'; 3import axios from 'axios'; 4import { useRouter } from 'next/router'; 5 6const CreateItem = () => { 7 const [name, setName] = useState(''); 8 const router = useRouter(); 9 10 const handleSubmit = async (e) => { 11 e.preventDefault(); 12 const newItem = { id: Date.now(), name }; 13 14 // Normally you would send this to your backend 15 await axios.post('/api/items', newItem); 16 router.push('/'); 17 }; 18 19 return ( 20 <div> 21 <h1>Create New Item</h1> 22 <form onSubmit={handleSubmit}> 23 <input 24 type="text" 25 value={name} 26 onChange={(e) => setName(e.target.value)} 27 required 28 /> 29 <button type="submit">Create</button> 30 </form> 31 </div> 32 ); 33}; 34 35export default CreateItem;
Step 4: Create an Edit Page (Update)
Create a new file named edit/[id].js
in the pages
directory:
javascript1// pages/edit/[id].js 2import { useEffect, useState } from 'react'; 3import { useRouter } from 'next/router'; 4import axios from 'axios'; 5 6const EditItem = () => { 7 const router = useRouter(); 8 const { id } = router.query; 9 const [item, setItem] = useState({ name: '' }); 10 11 useEffect(() => { 12 const fetchItem = async () => { 13 const response = await axios.get('/data/items.json'); 14 const foundItem = response.data.find(i => i.id == id); 15 setItem(foundItem); 16 }; 17 if (id) fetchItem(); 18 }, [id]); 19 20 const handleSubmit = async (e) => { 21 e.preventDefault(); 22 // Normally you would send this to your backend 23 await axios.put(`/api/items/${id}`, item); 24 router.push('/'); 25 }; 26 27 return ( 28 <div> 29 <h1>Edit Item</h1 <form onSubmit={handleSubmit}> 30 <input 31 type="text" 32 value={item.name} 33 onChange={(e) => setItem({ ...item, name: e.target.value })} 34 required 35 /> 36 <button type="submit">Update</button> 37 </form> 38 </div> 39 ); 40}; 41 42export default EditItem;
Step 5: Set Up API Routes (Delete)
Next.js allows you to create API routes to handle backend logic. Create a new folder named api
inside the pages
directory and add a file named items.js
:
javascript1// pages/api/items.js 2import items from '../../data/items.json'; 3 4export default function handler(req, res) { 5 if (req.method === 'GET') { 6 res.status(200).json(items); 7 } else if (req.method === 'POST') { 8 const newItem = req.body; 9 items.push(newItem); 10 res.status(201).json(newItem); 11 } else if (req.method === 'PUT') { 12 const { id } = req.query; 13 const index = items.findIndex(item => item.id == id); 14 if (index !== -1) { 15 items[index] = { ...items[index], ...req.body }; 16 res.status(200).json(items[index]); 17 } else { 18 res.status(404).json({ message: 'Item not found' }); 19 } 20 } else if (req.method === 'DELETE') { 21 const { id } = req.query; 22 const index = items.findIndex(item => item.id == id); 23 if (index !== -1) { 24 items.splice(index, 1); 25 res.status(204).end(); 26 } else { 27 res.status(404).json({ message: 'Item not found' }); 28 } 29 } else { 30 res.setHeader('Allow', ['GET', 'POST', 'PUT', 'DELETE']); 31 res.status(405).end(`Method ${req.method} Not Allowed`); 32 } 33}
Step 6: Testing the Application
Now that you have set up the CRUD functionality, you can run your application:
bash1npm run dev
Visit http://localhost:3000
in your browser. You should be able to create, read, update, and delete items in your application.
Conclusion
In this tutorial, you learned how to create a simple CRUD application using Next.js. You can expand this application by integrating a real database, adding user authentication, or implementing more complex features. ### Step 7: Implementing Delete Functionality
To implement the delete functionality, we need to add a delete button to the item list and handle the delete request in the API route.
First, let's add a delete button to the item list in the pages/index.js
file:
javascript1// pages/index.js 2import Link from 'next/link'; 3import axios from 'axios'; 4import { useEffect, useState } from 'react'; 5 6const Home = () => { 7 const [items, setItems] = useState([]); 8 9 useEffect(() => { 10 const fetchItems = async () => { 11 const response = await axios.get('/data/items.json'); 12 setItems(response.data); 13 }; 14 fetchItems(); 15 }, []); 16 17 const handleDelete = async (id) => { 18 await axios.delete(`/api/items/${id}`); 19 setItems(items.filter(item => item.id !== id)); 20 }; 21 22 return ( 23 <div> 24 <h1>Items List</h1> 25 <Link href="/create">Create New Item</Link> 26 <ul> 27 {items.map(item => ( 28 <li key={item.id}> 29 {item.name} - 30 <Link href={`/edit/${item.id}`}>Edit</Link> - 31 <button onClick={() => handleDelete(item.id)}>Delete</button> 32 </li> 33 ))} 34 </ul> 35 </div> 36 ); 37}; 38 39export default Home;
Now, when you click the delete button, the item will be deleted from the list and the API route will be called to delete the item.
Step 8: Handling Errors
To handle errors, we can add try-catch blocks to our API routes and error handling functions to our frontend code.
Let's add a try-catch block to our API route in the pages/api/items.js
file:
javascript1// pages/api/items.js 2import items from '../../data/items.json'; 3 4export default function handler(req, res) { 5 try { 6 if (req.method === 'GET') { 7 res.status(200).json(items); 8 } else if (req.method === 'POST') { 9 const newItem = req.body; 10 items.push(newItem); 11 res.status(201).json(newItem); 12 } else if (req.method === 'PUT') { 13 const { id } = req.query; 14 const index = items.findIndex(item => item.id == id); 15 if (index !== -1) { 16 items[index] = { ...items[index], ...req.body }; 17 res.status(200).json(items[index]); 18 } else { 19 res.status(404).json({ message: 'Item not found' }); 20 } 21 } else if (req.method === 'DELETE') { 22 const { id } = req.query; 23 const index = items.findIndex(item => item.id == id); 24 if (index !== -1) { 25 items.splice(index, 1); 26 res.status(204).end(); 27 } else { 28 res.status(404).json({ message: 'Item not found' }); 29 } 30 } else { 31 res.setHeader('Allow', ['GET', 'POST', 'PUT', 'DELETE']); 32 res.status(405).end(`Method ${req.method} Not Allowed`); 33 } 34 } catch (error) { 35 console.error(error); 36 res.status(500).json({ message: 'Internal Server Error' }); 37 } 38}
Now, if an error occurs in our API route, it will be caught and a 500 error will be returned to the frontend.
Let's add error handling functions to our frontend code in the pages/index.js
file:
javascript1// pages/index.js 2import Link from 'next/link'; 3import axios from 'axios'; 4import { useEffect, useState } from 'react'; 5 6const Home = () => { 7 const [items, setItems] = useState([]); 8 const [error, setError] = useState(null); 9 10 useEffect(() => { 11 const fetchItems = async () => { 12 try { 13 const response = await axios.get('/data/items.json'); 14 setItems(response.data); 15 } catch (error) { 16 setError(error.message); 17 } 18 }; 19 fetchItems(); 20 }, []); 21 22 const handleDelete = async (id) => { 23 try { 24 await axios.delete(`/api/items/${id}`); 25 setItems(items.filter(item => item.id !== id)); 26 } catch (error) { 27 setError(error.message); 28 } 29 }; 30 31 return ( 32 <div> 33 <h1>Items List</h1> 34 <Link href="/create">Create New Item</Link> 35 {error ? ( 36 <p style={{ color: 'red' }}>{error}</p> 37 ) : ( 38 <ul> 39 {items.map(item => ( 40 <li key={item.id}> 41 {item.name} - 42 <Link href={`/edit/${item.id}`}>Edit</Link> - 43 <button onClick={() => handleDelete(item.id)}>Delete</button> 44 </li> 45 ))} 46 </ul> 47 )} 48 </div> 49 ); 50}; 51 52export default Home;
Now, if an error occurs when fetching or deleting items, an error message will be displayed to the user. ### Step 9: Styling the Application
To improve the user experience, we can add some basic styling to our application. You can use CSS modules or global styles. For simplicity, let's add some global styles.
- Create a new file named
globals.css
in thestyles
directory:
css1/* styles/globals.css */ 2body { 3 font-family: Arial, sans-serif; 4 margin: 0; 5 padding: 0; 6 background-color: #f4f4f4; 7} 8 9h1 { 10 color: #333; 11} 12 13a { 14 text-decoration: none; 15 color: #0070f3; 16} 17 18a:hover { 19 text-decoration: underline; 20} 21 22ul { 23 list-style-type: none; 24 padding: 0; 25} 26 27li { 28 background: #fff; 29 margin: 10px 0; 30 padding: 10px; 31 border-radius: 5px; 32 display: flex; 33 justify-content: space-between; 34 align-items: center; 35} 36 37button { 38 background-color: #e63946; 39 color: white; 40 border: none; 41 padding: 5px 10px; 42 border-radius: 5px; 43 cursor: pointer; 44} 45 46button:hover { 47 background-color: #d62839; 48}
- Import the global styles in your
_app.js
file:
javascript1// pages/_app.js 2import '../styles/globals.css'; 3 4function MyApp({ Component, pageProps }) { 5 return <Component {...pageProps} />; 6} 7 8export default MyApp;
Step 10: Deploying the Application
Once you are satisfied with your application, you can deploy it. Vercel is the recommended platform for deploying Next.js applications.
- Sign up for a Vercel account if you don't have one.
- Install the Vercel CLI globally:
bash1npm install -g vercel
- Deploy your application by running the following command in your project directory:
bash1vercel
- Follow the prompts to link your project to your Vercel account and deploy it.
Conclusion
You have now built a complete CRUD application using Next.js, complete with create, read, update, and delete functionalities. You also learned how to handle errors and style your application. This foundational knowledge can be expanded upon to create more complex applications with additional features and integrations. Happy coding!
- Get link
- X
- Other Apps
Comments
Post a Comment