Using a React Hooks and React Router v6, how do you load and define data on parent Events
load and then pass subset of events data to the dynamic nested route -- campaign
. I am planning to define and set state of Campaigns within the Events
Route.
Since I am defining the routing on the index.js file, I am trying to see how to best pass this data from the parent Route to the nested Route, since the data is not yet defined in the index.js
view.
<Route path="events" element={<Events />}>
<Route path=":event" element={<Event campaign={campaign} />} />
</Route>
CodePudding user response:
If you can't pass something via props, and it cannot be derived by the route params, you'd use context instead.
In your example, <Event />
will be rendered where you place <Outlet />
. You can wrap a context provider around your usage of <Outlet />
within the <Events />
component:
const MyContext = React.createContext();
const Events = () => {
return <MyContext.Provider value={{greeting: "Hello, world!"}}>
<Outlet />
</MyContext.Provider>;
};
And then you can access this value within the event component by using that same context:
const Event = () => {
const { greeting } = React.useContext(MyContext);
return <span>{greeting}</span>;
};
In order to make code easier to follow, where possible, I would recommend propagating information in the following preference order:
- Via props to the child component (either by passing the data itself, or some ID of the data which can be used to retrieve it from a data store)
- Have the child component determine the information from the URL
- Pass data from parent to child via context
This is also in order of explicitness - be more explicit where possible.
For your precise example, I would recommend using a combination of context and ids; each Campaign likely has its own ID, so I'd design an API that looked like this:
const Events = () => {
const campaignStore = useCampaignStore();
return <CampaignContext.Provider value={campaignStore}>
<React.Suspense fallback={<span>Loading...</span>}>
<Outlet />
</React.Suspense>
<CampaignContext.Provider>
}
const Event = ({ campaignID }) => {
const campaign = useCampaign(campaignID);
....
}
Where useCampaign
would be some hook that would throw to enable suspense if a value was not yet available.