You have the option to lift it to either level.
If you choose to lift state to the App
, you can pass necessary data down as props to each routed component.
For instance:
function App() {
const [contacts, setContacts] = useState([]);
return (
<BrowserRouter>
<Routes>
<Route element={<Layout />}>
<Route
path="/"
element={<ContactList contacts={contacts} />}
/>
<Route
path="/add"
element={<AddContact setContacts={setContacts} />}
/>
</Route>
</Routes>
</BrowserRouter>
);
}
Alternatively, placing the state in the Layout
route component and making it accessible through the Outlet
component's context is another approach. The subsequent components would then utilize the provided context value using the useOutletContext
hook.
function App() {
return (
<BrowserRouter>
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<ContactList />} />
<Route path="/add" element={<AddContact />} />
</Route>
</Routes>
</BrowserRouter>
);
}
const Layout = () => {
const [contacts, setContacts] = useState([]);
return (
...
<Outlet context={{ contacts, setContacts }} />
...
);
};
const ContactList = () => {
const { contacts } = useOutletContext();
...
};
const AddContact = () => {
const { setContacts } = useOutletContext();
...
};
Ultimately, your choice might depend on personal preference or scope, such as the amount of the sub-ReactTree that requires access to the state.