Building a basic CRUD (Create, Read, Update, Delete) app in React with Material UI (MUI) version 5 requires a series of steps. Here’s an illustration of creating such an app within a single page. While this example covers the essential components for CRUD operations, it doesn’t encompass advanced functionalities like API integration or error handling.
Install & Setup Vite + React + Typescript + MUI 5
React MUI 5 Simple CRUD App
Splitting your CRUD application into separate components is a good practice for maintainability and readability. Here’s an example of how you can split the previous single-page application into multiple components:
1. App Component: The main component that will render other components.
2. AddItemForm: A component for adding new items.
3. EditItemForm: A component for editing existing items.
4. ItemsTable: A component to display the list of items.
import { useState } from 'react';
import { Container } from '@mui/material';
import AddItemForm from './AddItemForm';
import EditItemForm from './EditItemForm';
import ItemsTable from './ItemsTable';
function App() {
const [items, setItems] = useState([]);
const [editing, setEditing] = useState(false);
const [currentItem, setCurrentItem] = useState({ id: null, name: '' });
const addItem = item => {
item.id = items.length + 1;
setItems([...items, item]);
};
const deleteItem = id => {
setItems(items.filter(item => item.id !== id));
};
const updateItem = (id, updatedItem) => {
setEditing(false);
setItems(items.map(item => (item.id === id ? updatedItem : item)));
};
const editRow = item => {
setEditing(true);
setCurrentItem({ id: item.id, name: item.name });
};
return (
<Container>
<h1>CRUD App with React</h1>
{editing ? (
<EditItemForm
editing={editing}
setEditing={setEditing}
currentItem={currentItem}
updateItem={updateItem}
/>
) : (
<AddItemForm addItem={addItem} />
)}
<ItemsTable items={items} editRow={editRow} deleteItem={deleteItem} />
</Container>
);
}
export default App;
AddItemForm Component
import { useState } from 'react';
import { TextField, Button } from '@mui/material';
const AddItemForm = props => {
const initialFormState = { id: null, name: '' };
const [item, setItem] = useState(initialFormState);
const handleInputChange = event => {
const { name, value } = event.target;
setItem({ ...item, [name]: value });
};
return (
<form
onSubmit={event => {
event.preventDefault();
if (!item.name) return;
props.addItem(item);
setItem(initialFormState);
}}
>
<TextField name="name" size="small" label="Name" value={item.name} onChange={handleInputChange} />
<Button type="submit" variant="contained">Add new item</Button>
</form>
);
};
export default AddItemForm;
EditItemForm Component
import { useState, useEffect } from 'react';
import { TextField, Button } from '@mui/material';
const EditItemForm = props => {
const [item, setItem] = useState(props.currentItem);
useEffect(() => {
setItem(props.currentItem);
}, [props]);
const handleInputChange = event => {
const { name, value } = event.target;
setItem({ ...item, [name]: value });
};
return (
<form
onSubmit={event => {
event.preventDefault();
props.updateItem(item.id, item);
}}
>
<TextField name="name" size="small" label="Name" value={item.name} onChange={handleInputChange} />
<Button type="submit" variant="contained">Update item</Button>
<Button onClick={() => props.setEditing(false)}>Cancel</Button>
</form>
);
};
export default EditItemForm;
ItemsTable Component
import { Table, TableBody, TableCell, TableHead, TableRow, Button } from '@mui/material';
const ItemsTable = props => {
return (
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.items.length > 0 ? (
props.items.map(item => (
<TableRow key={item.id}>
<TableCell>{item.id}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>
<Button onClick={() => props.editRow(item)}>Edit</Button>
<Button onClick={() => props.deleteItem(item.id)}>Delete</Button>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={3}>No items</TableCell>
</TableRow>
)}
</TableBody>
</Table>
);
};
export default ItemsTable;