mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
2.5 KiB
2.5 KiB
Routing & Unsaved Changes
This frontend uses React Router v6 in data router mode (createBrowserRouter + RouterProvider). This enables useBlocker and related APIs for navigation interception.
Data Router Basics
- Entry point:
frontend/src/router/index.tsxexports the router created withcreateBrowserRouterand is consumed byRouterProviderinfrontend/src/main.tsx. - Global layout:
Apprenders global chrome and anOutletfor child routes. - When adding routes, define them in
router/index.tsxusing the data-router configuration (array orcreateRoutesFromElements).
Enabling Unsaved-Changes Prompts
Unsaved-change blocking is provided by UnsavedChangesProvider and the useUnsavedChangesPrompt hook.
Provider
- Wrap any page containing a form or editable detail view with
UnsavedChangesProvider. - The provider listens to
useBlockerand renders the shared confirmation dialog.
Hook
- In a form component, call
const { setDirty } = useUnsavedChangesPrompt(isDirty)whereisDirtycomes from your form state (react-hook-form’sformState.isDirty, etc.). - Set dirty to
falseimmediately before/after a successful submit so navigation to the next page isn’t blocked. - If submit fails, set dirty back to
trueso protection remains while the user fixes errors.
Minimal Example
import { useForm } from 'react-hook-form';
import { UnsavedChangesProvider } from '@/components/UnsavedChangesProvider';
import { useUnsavedChangesPrompt } from '@/hooks/useUnsavedChangesPrompt';
export const ExampleFormPage = () => {
const { handleSubmit, formState: { isDirty }, reset } = useForm();
const { setDirty } = useUnsavedChangesPrompt(isDirty);
const onSubmit = handleSubmit(async values => {
setDirty(false);
try {
await save(values);
reset(values);
} catch {
setDirty(true);
throw new Error('Save failed');
}
});
return (
<UnsavedChangesProvider>
<form onSubmit={onSubmit}>
{/* form fields */}
<button type="submit">Save</button>
</form>
</UnsavedChangesProvider>
);
};
Detail Views
- For detail pages that use shared context (e.g.,
DetailView), place the provider at the page level and wireuseUnsavedChangesPromptto the context’sisDirtyflag inside a small tracker component.
Notes
useBlockerrequires the data router; ensure new routes continue to usecreateBrowserRouter.- The dialog text can be customized via
UnsavedChangesProviderprops or by passing amessageoption touseUnsavedChangesPrompt.