KvS
KvS

Reputation: 82

`location.state` in dependency of `useEffect` not getting triggered for the initial rendering of component

I have a parent component which is having Outlet for sub routes.

I wanted to pass the data from the parent component (App.js) to the component rendered by Outlet for the default Link (Test.js).

For which, I used the state object of location and passed the data from parent Component.

<Link to="" state={{ data }}>
  Render test
</Link>

Although on initial render, it is still null in child component (Test.js), but if I navigate to some other route (route: /dummy, component : Dummy.js) within that parent and come back to Test.js components route, I am able to see value in the location.state.

Codesandbox link for more clarity: https://codesandbox.io/s/location-state-zjs5rt

I tried adding location.state as dependency in useEffect but it is not getting triggered on the initial render.

useEffect(() => {
  if (location.state) {
    setTestData(location.state.data);
  }
}, [location?.state]);

I wanted to pass some async data from App.js and use it inside Test.js component to render certain things, how can I achieve this?

Upvotes: 1

Views: 481

Answers (1)

Drew Reese
Drew Reese

Reputation: 203562

If you are just wanting to make available some state in the App component to any of the nested route's element components then I'd suggest passing it via the React context available via the Outlet component. The routed components use the useOutletContext hook to access the context.

Example:

App

import { Outlet, Link } from "react-router-dom";
import { useEffect, useState } from "react";

export default function App() {
  const [data, setData] = useState(null);

  useEffect(() => {
    setTimeout(() => {
      setData("data that comes later");
    }, 2000);
  }, []);

  return (
    <div className="App">
      {data ? (
        <>
          <h2>This is APP component</h2>
          <ul>
            <li>
              <Link to="/">Render test</Link>
            </li>
            <li>
              <Link to="/dummy">Another dummy component</Link>
            </li>
          </ul>
          <Outlet context={{ data }} /> // <-- passed in context
        </>
      ) : (
        <>Loading...</>
      )}
    </div>
  );
}

Test

import { useEffect } from "react";
import { useOutletContext } from "react-router-dom";

export default function Test(props) {
  const { data } = useOutletContext();

  useEffect(() => {
    console.log("data using location", data);
  }, [data]);

  return <div>This is another component "{data}"</div>;
}

Edit location-state-in-dependency-of-useeffect-not-getting-triggered-for-the-init

Upvotes: 1

Related Questions