AI Reading
Quick summary of this article
This guide shows how to build a React frontend for a Node.js and MongoDB CRUD app that supports image upload. It uses Vite to create the React project, Axios for API calls, and React Router for navigation between the user list, add user, and edit user pages.
- The React app is created with Vite and installs
axiosandreact-router-dom. - A shared Axios instance in
src/api.jsconnects the frontend to the backend athttp://localhost:5000. - Routes are set up in
App.jsfor the user list (/), add user (/add), and edit user (/edit/:id). UserList.jsfetches users, displays profile images, and allows deleting users.UserForm.jsandEditUser.jshandle adding and updating users, including image uploads throughFormData.
⚛️ React Frontend for Node.js + MongoDB CRUD App with Image Upload
In this section, we will build the React.js frontend that connects to the Node.js API we created earlier. The frontend will allow users to create, view, edit, and delete users — along with uploading and displaying profile images.
📁 React Project Structure
We will use Axios for API communication and React Router for navigation.
user-crud-frontend/
│ package.json
│
└───src
│ App.js
│ index.js
│ api.js
│
└───components
│ UserList.js
│ UserForm.js
│ EditUser.js
📦 Step 1: Install React App with Vite & Dependencies
Instead of using create-react-app, we’ll use Vite — a fast and modern build tool. This also works seamlessly with React Router and Axios.
# Install Vite and create a React app
npm create vite@latest user-crud-frontend -- --template react
# Move into the project folder
cd user-crud-frontend
# Install dependencies
npm install
# Install Axios and React Router DOM
npm install axios react-router-dom
# Start the development server
npm run dev
🔗 Step 2: Axios API File – src/api.js
import axios from 'axios';
const API = axios.create({
baseURL: 'http://localhost:5000', // Your backend URL
});
export default API;
🔁 Step 3: React Routing – src/App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import UserList from './components/UserList';
import UserForm from './components/UserForm';
import EditUser from './components/EditUser';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={} />
<Route path="/add" element={} />
<Route path="/edit/:id" element={} />
</Routes>
</Router>
);
}
export default App;
👥 Step 4: User List – src/components/UserList.js
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import API from '../api';
function UserList() {
const [users, setUsers] = useState([]);
const fetchUsers = async () => {
const res = await API.get('/api/users');
setUsers(res.data);
};
const deleteUser = async (id) => {
await API.delete(`/api/users/${id}`);
fetchUsers();
};
useEffect(() => {
fetchUsers();
}, []);
return (
<div>
<h2>User List</h2>
<Link to="/add">Add New User</Link>
<ul>
{users.map(user => (
<li key={user._id}>
<img
src={`http://localhost:5000/uploads/${user.image}`}
alt="user"
width="50"
height="50"
/>
{user.first_name} {user.last_name} - {user.email}
<Link to={`/edit/${user._id}`}>Edit</Link>
<button onClick={() => deleteUser(user._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default UserList;
➕ Step 5: Add User – src/components/UserForm.js
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import API from '../api';
function UserForm() {
const [form, setForm] = useState({
first_name: '',
last_name: '',
email: '',
password: '',
image: null,
});
const navigate = useNavigate();
const handleChange = (e) => {
const { name, value, files } = e.target;
setForm({ ...form, [name]: files ? files[0] : value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
Object.entries(form).forEach(([key, value]) => formData.append(key, value));
await API.post('/api/users', formData);
navigate('/');
};
return (
<form onSubmit={handleSubmit}>
<h2>Add User</h2>
<input name="first_name" placeholder="First Name" onChange={handleChange} />
<input name="last_name" placeholder="Last Name" onChange={handleChange} />
<input name="email" placeholder="Email" onChange={handleChange} />
<input name="password" type="password" placeholder="Password" onChange={handleChange} />
<input type="file" name="image" onChange={handleChange} />
<button type="submit">Create</button>
</form>
);
}
export default UserForm;
✏️ Step 6: Edit User – src/components/EditUser.js
import React, { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import API from '../api';
function EditUser() {
const { id } = useParams();
const [form, setForm] = useState({
first_name: '',
last_name: '',
email: '',
password: '',
image: null,
});
const navigate = useNavigate();
useEffect(() => {
API.get(`/api/users/${id}`).then(res => setForm(res.data));
}, [id]);
const handleChange = (e) => {
const { name, value, files } = e.target;
setForm({ ...form, [name]: files ? files[0] : value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
Object.entries(form).forEach(([key, value]) => {
if (value !== null) formData.append(key, value);
});
await API.put(`/api/users/${id}`, formData);
navigate('/');
};
return (
<form onSubmit={handleSubmit}>
<h2>Edit User</h2>
<input name="first_name" value={form.first_name} onChange={handleChange} />
<input name="last_name" value={form.last_name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<input name="password" type="password" onChange={handleChange} />
<input type="file" name="image" onChange={handleChange} />
<button type="submit">Update</button>
</form>
);
}
export default EditUser;
