React Router dom v6: are loaders "observables"?
So I have 3 components, App, which has the outlet, then a component to add users and a component to list users (it's a dummy app, I'm exploring react router dom).
In the App component I also list the number of users currently stored.
These are my action and loader:
const databaseMock: User[] = [{ id: 1, name: 'John Doe' }];
export function rootLoader() {
return { users: databaseMock };
}
export async function action({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const name = formData.get('name');
databaseMock.push({
id: new Date().getMilliseconds(),
name: name?.toString() ?? '',
});
return redirect('/users');
}
And that's my router setup:
const router = createBrowserRouter([
{
path: '/',
element: <App />,
loader: rootLoader,
children: [
{
path: 'users/add',
element: <UserForm />,
action,
loader: rootLoader,
},
{
path: 'users',
element: <Users />,
loader: rootLoader,
},
],
},
]);
My question is now, WHY does it work when I add a new user from <UserForm> that my main <App> component picks up on the changes? Here's the implementation of App and UserForm:
// App.tsx
function App() {
const { users } = useLoaderData();
return (
<>
<Header reactLogo={reactLogo} viteLogo={viteLogo} />
<div className="card">
<h2>{users.length}</h2>
<Outlet />
</div>
<Footer />
</>
);
}
// UserForm.tsx
export const UserForm = (): JSX.Element => {
return (
<>
<Form method="post">
<input type="text" name="name" />
<button type="submit">Save</button>
</Form>
</>
);
};
Why does purely pushing something to array (in action) rerender App when I submit the form? How's this implemented in react router dom?
I wasn't expecting that number of users will be immediately updated, I thought I'll have to reload it somehow so that "useLoaderData" will be called again.