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
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
As I can see you have used Link for navigation.
Try to use useRouter() and navigate with push.
eg.
When navigating between URLs and you want to maintain state, use
useSearchParams()
anduseNavigate
from React Router DOM.More information can be found here.