new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React Router · Getting started · all subjects

actions/basics

17 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Actions property on route object

Route actions are defined on the `action` property of a route object. Actions handle data mutations. When an action completes, all loader data on the page is automatically revalidated to keep the UI in sync with data.

Action parameter: request

Actions receive a request object as a parameter. You can extract form data from the request using `await request.formData()` to get a FormData object, then retrieve individual fields using `.get(fieldName)`.

Full action definition example

This example shows a complete action definition: `{ path: "/projects/:projectId", Component: Project, action: async ({ request }) => { let formData = await request.formData(); let title = formData.get("title"); let project = await someApi.updateProject({ title }); return project; } }`

Data mutations done through Route actions

Data mutations in React Router are performed through Route actions. When an action completes, all loader data on the page is automatically revalidated to keep the UI in sync with the data without requiring manual code to handle synchronization.

Server actions vs client actions definition

Route actions defined with the 'action' export only run on the server and are removed from client bundles. Route actions defined with 'clientAction' export run in the browser. Client actions take priority over server actions when both are defined on the same route.

Server action function signature and example

A server action function receives Route.ActionArgs containing a request object. The function is async and retrieves formData from request.formData(), then processes it and returns data. Example: export async function action({ request }: Route.ActionArgs) { let formData = await request.formData(); let title = formData.get('title'); let project = await fakeDb.updateProject({ title }); return project; }

Access action data in component

Action data returned from an action is accessible in the route component through Route.ComponentProps. The component receives actionData which contains the data returned by the action and can be undefined if no action has been called yet.

useFetcher for independent pending state

The useFetcher hook provides independent pending state for form submissions without causing global navigation. It has a state property that can be checked against 'idle' to determine if a submission is in progress. useFetcher also provides a Form component for submitting data.

useFetcher form submission pending state

Use fetcher.state to check form submission status. When fetcher.state is not 'idle', the form is submitting. Display appropriate UI feedback such as 'Submitting...' text on the submit button.

useNavigation for non-fetcher form pending state

For form submissions using Form component instead of fetcher.Form, use useNavigation() to check pending state. The navigation.formAction property contains the action URL of the submitted form. Compare this to the expected action to determine if that specific form is submitting.

Optimistic UI with fetcher.formData

Implement optimistic UI by checking fetcher.formData during form submission. The formData contains the submitted form fields. Use formData.get(fieldName) to read submitted values and update the UI optimistically before the server responds.

redirect helper for returning navigation Response

Use `redirect(url)` from react-router to return a Response that tells the app to change locations. Example: `return redirect('/contacts/123')`. With client-side routing, this is a client-side redirect so users don't lose scroll positions or component state. Works like a normal server redirect without JavaScript.

Form component for data mutations

Use `<Form>` from react-router instead of HTML `<form>` for data mutations. Forms prevent browser default behavior, serialize form data, and send it to the route's `action` function via fetch instead of to the server. This emulates HTML form navigation with client-side routing.

action function for handling form submissions

Export an async `action()` function from a route module to handle form submissions. Receives a request with serialized form data. Usage: `export async function action({ params, request }: Route.ActionArgs) { const formData = await request.formData(); const updates = Object.fromEntries(formData); await updateContact(params.contactId, updates); return redirect(...); }` After action completes, React Router automatically revalidates loaders.

Relative Form action attribute

Like `<Link to>`, `<Form action>` accepts relative values. When in route contacts/:contactId, `<Form action='destroy'>` submits to contacts/:contactId/destroy. This allows modular route actions without hardcoding full paths.

GET forms for URL parameter changes

`<Form>` without `method='post'` (or with `method='get'`) serializes form data as URLSearchParams in the URL query string instead of the request body. No action function is called; only loaders run (normal page navigation). Useful for search/filter forms that don't mutate data.

POST form automatic replace behavior

When a POST form submission does not redirect, the router uses REPLACE in the history stack to avoid duplicate entries. When a POST form submission does redirect, the router uses PUSH for the redirect to preserve the history entry for the login page. Users can override this with the replace prop: <Form method="post" replace={shouldReplace}>.

Give your agent this brain