Home > Back-end >  Passing Data Between Route and Nested Route in React
Passing Data Between Route and Nested Route in React

Time:06-05

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:

  1. 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)
  2. Have the child component determine the information from the URL
  3. 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.

  • Related