DocsSection 10
10Section 10 of 10
Common Patterns
Common Patterns You'll See
10.1 Loading States
export default function DataPage() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
fetchData()
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <Loading />;
if (error) return <Error message={error} />;
return <DataView data={data} />;
}
10.2 Form Handling
export default function CreateForm() {
const [formData, setFormData] = useState({ name: '', email: '' });
const [submitting, setSubmitting] = useState(false);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
setSubmitting(true);
try {
await fetch('/api/clients', {
method: 'POST',
body: JSON.stringify(formData),
});
// Success - redirect or show message
} catch (error) {
// Show error
} finally {
setSubmitting(false);
}
};
return (
<form onSubmit={handleSubmit}>
<Input
value={formData.name}
onChange={e => setFormData({ ...formData, name: e.target.value })}
/>
<Button type="submit" loading={submitting}>
Create
</Button>
</form>
);
}
10.3 Optimistic Updates
// Update UI immediately, rollback on error
const handleDelete = async (id: string) => {
// Optimistic: remove from UI
setLeads(leads.filter(l => l.id !== id));
try {
await fetch(`/api/sales/leads/${id}`, { method: 'DELETE' });
} catch (error) {
// Rollback: add back to UI
setLeads(originalLeads);
showError('Failed to delete');
}
};
10.4 Debounced Search
const [search, setSearch] = useState('');
const [results, setResults] = useState([]);
useEffect(() => {
const timer = setTimeout(() => {
if (search) {
fetch(`/api/search?q=${search}`)
.then(r => r.json())
.then(setResults);
}
}, 300); // Wait 300ms after typing stops
return () => clearTimeout(timer);
}, [search]);
Summary
You Now Understand:
✅ Stack: Next.js 16 + TypeScript + Tailwind + SQLite
✅ Structure: How files map to routes
✅ Data Flow: Client vs server rendering
✅ Auth: Session-based with role checks
✅ Database: SQLite with parameterized queries
✅ Frontend: Component hierarchy + Tailwind
✅ APIs: RESTful routes with middleware
✅ Security: Defense in depth
✅ Patterns: Loading states, forms, optimistic updates
Key Takeaways:
- Next.js App Router = file-system routing
- Server components = faster initial load, better SEO
- Client components = interactivity, real-time updates
- Database queries = always parameterized
- Auth = middleware + session cookies + role checks
- Components = reusable UI primitives
- APIs = RESTful with proper error handling
Next Steps:
- Read
lib/db/index.tsto understand database patterns - Look at
app/api/clients/route.tsfor API patterns - Study
app/components/ui/for component patterns - Review
middleware.tsfor auth flow