Content description:
In this article, I'll show you how to create a new warehouse and edit an existing one using a front-end built in React (the back-end API was built in DRF).
First, I add the components of the pages responsible for creating a new warehouse and editing an existing one to the router in the main App.jsx component.
import WarehouseAddPage from "./pages/WarehouseAddPage"
import WarehouseEditPage from "./pages/WarehouseEditPage"
import { warehouseLoader } from "./components/Warehouse"
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<MainLayout/>}>
<Route index element={<MainPage/>} />
<Route path="/login/" element={<LoginPage/>} />
<Route path="/logout" element={<LogoutPage/>} />
<Route path="/register" element={<RegisterPage/>} />
<Route path="/warehouses" element={<WarehousesPage/>} />
<Route path="/warehouses/:id" element={<WarehousePage/>} loader={warehouseLoader} />
<Route path="/add-warehouse" element={<WarehouseAddPage/>} />
<Route path="/edit-warehouse/:id" element={<WarehouseEditPage/>} loader={warehouseLoader} />
<Route path="*" element={<ErrorPage/>} />
</Route>
)
)
function App() {
return (
<RouterProvider router={router} />
)
}
export default App
The WarehouseAddPage component calls the form component and additionally the legend variable is sent as a parameter.
import WarehouseForm from "../components/WarehouseForm"
function WarehouseAddPage() {
return (
)
}
export default WarehouseAddPage
The WarehouseEditPage component works in a similar way and additionally sends the warehouse id and data of that warehouse to the form component.
import WarehouseForm from "../components/WarehouseForm"
import { useParams, useLoaderData } from "react-router-dom"
function WarehouseEditPage() {
const {id} = useParams()
const warehouse = useLoaderData()
return (
<>
<WarehouseForm legend="Edit Warehouse" id={id} warehouse={warehouse}/>
</>
)
}
export default WarehouseEditPage
The form component is common to both page components. In case of editing, the form displays already existing warehouse data.
import { useState } from "react"
import { useNavigate, useLocation } from "react-router-dom"
function WarehouseForm({legend, id=null, warehouse=null}) {
const navigate = useNavigate()
const location = useLocation()
const [warehouseName, setWarehouseName] = useState(warehouse? warehouse.warehouse_name: "")
const [warehouseInfo, setWarehouseInfo] = useState(warehouse? warehouse.warehouse_info: "")
const handleForm = async (e) => {
e.preventDefault()
try {
const token = localStorage.getItem('accessToken')
let res;
if (id === null) {
res = await fetch('/api/warehouses/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({"warehouse_name":warehouseName, "warehouse_info": warehouseInfo})
})
} else {
res = await fetch(`/api/warehouses/${id}/`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({"warehouse_name":warehouseName, "warehouse_info": warehouseInfo})
})
}
if (res.status==401) {
const token = localStorage.getItem('refreshToken')
const res = await fetch('/api/token/refresh/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({"refresh": token})
})
if (res.ok) {
const data = await res.json()
localStorage.setItem("accessToken", data["access"])
handleForm()
} else {
navigate('/login', {state: {"from": location.pathname}})
}
}
navigate(`/warehouses/`)
} catch (err) {
console.error(err)
}
}
return (
<form onSubmit={handleForm}>
<legend>{legend}</legend>
<div>
<label>Warehouse name:</label>
<input
type="text"
value={warehouseName}
onChange={(e) => setWarehouseName(e.target.value)}
required
/>
</div>
<div>
<label>Warehouse info:</label>
<input
type="text"
value={warehouseInfo}
onChange={(e) => setWarehouseInfo(e.target.value)}
required
/>
</div>
<button type="submit">Submit</button>
<button type="button" onClick={() =>navigate('/warehouses')}>Cancel</button>
</form>
)
}
export default WarehouseForm