mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Document data router and unsaved changes usage
This commit is contained in:
@@ -16,3 +16,7 @@ Ensure the "Return to table" button in detail views respects the originating Upd
|
|||||||
- End-to-end flow: `npx cypress run --spec cypress/e2e/updateLogNavigation.cy.ts` (requires the application and database running locally).
|
- End-to-end flow: `npx cypress run --spec cypress/e2e/updateLogNavigation.cy.ts` (requires the application and database running locally).
|
||||||
|
|
||||||
Record any deviations in the QA log and link failures to the associated test artifacts.
|
Record any deviations in the QA log and link failures to the associated test artifacts.
|
||||||
|
|
||||||
|
## Routing & Unsaved Changes
|
||||||
|
|
||||||
|
For guidance on the data router setup and enabling unsaved-change prompts for new forms, see [`docs/routing.md`](./docs/routing.md).
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# 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.tsx` exports the router created with `createBrowserRouter` and is consumed by `RouterProvider` in `frontend/src/main.tsx`.
|
||||||
|
- Global layout: `App` renders global chrome and an `Outlet` for child routes.
|
||||||
|
- When adding routes, define them in `router/index.tsx` using the data-router configuration (array or `createRoutesFromElements`).
|
||||||
|
|
||||||
|
## 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 `useBlocker` and renders the shared confirmation dialog.
|
||||||
|
|
||||||
|
**Hook**
|
||||||
|
- In a form component, call `const { setDirty } = useUnsavedChangesPrompt(isDirty)` where `isDirty` comes from your form state (`react-hook-form`’s `formState.isDirty`, etc.).
|
||||||
|
- Set dirty to `false` immediately before/after a successful submit so navigation to the next page isn’t blocked.
|
||||||
|
- If submit fails, set dirty back to `true` so protection remains while the user fixes errors.
|
||||||
|
|
||||||
|
### Minimal Example
|
||||||
|
```tsx
|
||||||
|
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 wire `useUnsavedChangesPrompt` to the context’s `isDirty` flag inside a small tracker component.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- `useBlocker` requires the data router; ensure new routes continue to use `createBrowserRouter`.
|
||||||
|
- The dialog text can be customized via `UnsavedChangesProvider` props or by passing a `message` option to `useUnsavedChangesPrompt`.
|
||||||
Reference in New Issue
Block a user