Search code examples
javascriptreactjsreact-router-dom

Maintain context values between routes in React.js


I'm trying to maintain state values between routes in context. But it gets reset when the route changes.

aackage.json:

 "react-router-dom": "^6.8.0",
 "react-dom": "^18.2.0",
 "react": "^18.2.0",

App.js:

export default const App = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(null);

  const getData = async () => {
    setLoading(true);
    const data = await axios.get("url", {
      withCredentials: true,
    });
    setData(data);
    setLoading(false);
  };

   useEffect(() => {
    getData()
    console.log("I run on route change");
  }, []);
  

  const GlobalContextValue= {
    data: data,
    loading: loading,
  };



   return (
    <>
      <GlobalContextProvider value={GlobalContextValue}>
      <BrowserRouter>
        <Routes>
          <Route index element={<HomePage />} />
          <Route path="/:slug" element={<PostPage />} />
          {/* <Route path="*" element={<NoPage />} /> */}
        </Routes>
      </BrowserRouter>
      </<GlobalContextProvider />
    </>
  )

}

Whenever I try to access any route the getData function inside the useEffect calls which inturns resets the data. I have attached a CodeSandbox to replicate the same

I don't know if this problem is related to reactJs or react-router. Thanks in advance


Solution

  • As you don't seem to have any navigation link, I assume you are using the browser search bar, or a normal HTML <a> tag. Well, doing so refreshes the page, so the entire app gets re-created.

    Using useNavigate or Link from React Router Dom, doesn't refresh the page, hence your context data remains untouched:

    const HomePage = () => {
      return (
        <>
          <h1>Hii Homepage </h1>
          <Link to="/1">Go to PostPage</Link>
        </>
      );
    };
    
    const PostPage = () => {
      const params = useParams();
      return (
        <>
          <h1>Hii PostPage {params.slug} </h1>
          <Link to="/">Go to HomePage</Link>
        </>
      );
    };
    
    export default function App() {
      useEffect(() => {
        console.log(
          "I run on load and route change with browser search bar, not with useNavigate or Link"
        );
      }, []);
    
      return (
        <>
          {/* This context wrapping BrowserRouter keeps its value if you navigate with Link or
          useNavigate. */}
          <GlobalContextProvider value={{ key: "some value" }}>
            <BrowserRouter>
              <Routes>
                <Route index element={<HomePage />} />
                <Route path="/:slug" element={<PostPage />} />
                {/* <Route path="*" element={<NoPage />} /> */}
              </Routes>
            </BrowserRouter>
          </GlobalContextProvider>
        </>
      );
    }