skip to Main Content

I’m facing an issue in my React application where I have multiple components, each with its own context using the useContext hook. I want to maintain the context for each component even if the URL changes.

I want to implement a behavior where, if I switch between tabs on a webpage and then navigate to another page through a link (e.g., ), the previously selected tab should remain active when I return to the original page(by back button of browser). Essentially, I am looking to maintain the state of the selected tab across page transitions.

Here is my code

Tab.js

import React, { useState, useCallback, createContext } from "react";

const TabContext = createContext({
  current: 0,
});

const Tab = ({ children }) => {
  const [current, setCurrent] = useState(0);

  const handleUpdateCurrent = useCallback((value) => {
    setCurrent(value);
  }, []);

  return (
    <TabContext.Provider value={{ current, handleUpdateCurrent }}>
      {children}
    </TabContext.Provider>
  );
};

export { Tab, TabContext };

TabListToggle.js


import React, { useContext } from "react";
import { TabContext } from "./Tab";

const TabListToggle = ({ data = [] }) => {

  const { current } = useContext(TabContext);
  const { handleUpdateCurrent } = useContext(TabContext);

  return (
    <div className="tabs-container">
      {data.map((value, index) => (
        <button
          key={index}
          onClick={() => handleUpdateCurrent(index)}
          className={`tab ${current === index ? "active" : ""}`}
          role="tab"
          aria-selected={current === index ? true : false}
        >
          <span>{value}</span>
        </button>
      ))}
    </div>
  );
};

export default TabListToggle;

Page1.js


import React from "react";
import { Link } from "react-router-dom";

import TabListToggle from "../components/TabListToggle";
import { Tab } from "../components/Tab";

const Page1 = () => {
  return (
    <div>
      <h1>Page1</h1>
      <Tab>
        <TabListToggle data={["Tab1", "Tab2","Tab3"]} />
        <div>
            <Link to="/page2/">Page2</Link>
        </div>
      </Tab>
    </div>
  );
};

export default Page1;

Page2.js

import React from "react";
import { Link } from "react-router-dom";
import TabListToggle from "../components/TabListToggle";
import { Tab } from "../components/Tab";

const Page2 = () => {
  return (
    <div>
      <h1>Page2</h1>
      <Tab>
        <TabListToggle data={["Tab1", "Tab2", "Tab3","Tab4"]} />
        <div>
        <Link to="/page1/">Page1</Link>
        </div>
      </Tab>
    </div>
  );
};

export default Page2;


App.js


const App = () => {
  const routeElement = useRoutes(routes);
  return routeElement;
  // return (
  //   <Tab>
  //     {routeElement}
  //   </Tab>
  // )
  
};

I tried to move Tab in app.js and remove the Tab component from the page1 and page2. This create a global state and changing one tab on one component changes the tab on the other pages which I dont want.

What am I doing wrong? Is it possible to achieve this using Context or i have to use localStorage ?

Please help.

3

Answers


  1. if you want to maintain context between multiple navigation then you should create context that wraps whole app and perform state operations in that context instead of individual context in separate components as when component unmounts context of that component gets destroyed and App.js is only component that destroys on refresh or page close

    Login or Signup to reply.
  2. As I can see you have used Link for navigation.

    Try to use useRouter() and navigate with push.

    eg.

    const router = useRouter();
    router.push("/page1")
    
    Login or Signup to reply.
  3. When navigating between URLs and you want to maintain state, use useSearchParams() and useNavigate from React Router DOM.

    1. Import the necessary hooks:
    import { useSearchParams, useNavigate } from 'react-router-dom';
    
    1. Navigate with a query parameter:
      const navigate = useNavigate();
      const handleClick = () => {
        // Use useNavigate to navigate to the "/other" route with a query parameter
        navigate('/other', { state: { value: 'exampleValue' } });
      };
    
    1. In the next page:
      let [searchParams, setSearchParams] = useSearchParams();
      const value = searchParams.get('value');
      // This value is the state from the navigate function used in the previous page.
    

    More information can be found here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search