React Request Form Project
Combine labelled fields, domain validation and an honest local result in one small form.
Your brief
Prepare a collection request with an allowed item, an integer quantity from one to three and a handling note. The form must reject unknown item values even if someone changes the browser markup. The note is optional and limited to 120 characters. The result is a local preview, not a booking. Before opening the solution, write accepted and rejected cases and decide whether each field needs controlled state or can be read on submit.
Run the code
Use a separate empty lab folder with Node 22.12+ in the 22 series. Save the files below using their displayed paths; browsers may download only the basename, so create src, public or tests folders as listed. The pinned project uses React and React DOM 19.3.1 with Vite 7.3.1. Run npm install, then npm run dev and open the local address Vite prints. React examples do not run in Bhylu’s current playground.
No Apache, MySQL or change to Bhylu’s server configuration is needed. These are local teaching projects, not a publishing package. Keep generated dependencies and lockfiles in your own lab. Review the project setup.
Worked solution
Show the worked solution
import React, { StrictMode, useState } from 'react';
import { createRoot } from 'react-dom/client';
import './style.css';
export function checkedRequest(data) {
const item = String(data.get('item') || '');
const quantity = String(data.get('quantity') || '').trim();
const note = String(data.get('note') || '').trim();
if (
!['basket', 'stool'].includes(item) ||
!/^[1-3]$/.test(quantity) ||
note.length > 120
)
return null;
return { item, quantity: Number(quantity), note };
}
function App() {
const [message, setMessage] = useState('No preview');
function preview(event) {
event.preventDefault();
const result = checkedRequest(new FormData(event.currentTarget));
setMessage(
result
? 'Local preview: ' + result.quantity + ' ' + result.item + '. Not reserved.'
: 'Check the item, quantity and note.',
);
}
return (
<main>
<h1>Neighbourhood lending desk</h1>
<form onSubmit={preview}>
<label>
Item
<select name="item" required>
<option value="basket">Basket</option>
<option value="stool">Stool</option>
</select>
</label>
<label>
Quantity
<input
name="quantity"
type="number"
min="1"
max="3"
step="1"
required
defaultValue="1"
/>
</label>
<label>
Handling note
<textarea name="note" maxLength={120} rows={3} />
</label>
<button>Preview locally</button>
</form>
<output aria-live="polite">{message}</output>
</main>
);
}
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
Expected result
Choosing stool and quantity three produces a local preview. Invalid domain values return no accepted request object.
checkedRequest is exported so the review can exercise malicious or malformed FormData independently of browser constraints. Native controls help ordinary users, while the function defines the local domain contract. A real server must repeat trusted validation and check authorization, inventory and duplicate requests. The preview intentionally does not save contact information or issue an identifier that looks like a confirmed booking.
Extend and test
Test empty, fractional and out-of-range quantities plus an unknown item and an overlong note. Add field-specific error messages without changing the local-only claim.
For API contracts and version differences, use React’s official documentation.