I have a simple menu and I have a page with a random context only for tests. Here my index.js
const Route = ReactRouterDOM.Route;
const Link = ReactRouterDOM.Link;
const HashRouter = ReactRouterDOM.HashRouter;
const Routes = ReactRouterDOM.Routes;
// create context
const UserContext = React.createContext(null);
function Spa() {
return (
<HashRouter>
<div>
<h1>Routing - Hello World</h1>
<Link to="/">Home</Link> --
<Link to="/about/">About</Link> --
<Link to="/products">Products</Link>
<hr />
<UserContext.Provider value={{ users: ["peter"] }}>
<Routes>
<Route path="/" exact element={ <Home />} />
<Route path="/about/" element={ <About />} />
<Route path="/products/" element={ <Products />} />
</Routes>
</UserContext.Provider>
</div>
</HashRouter>
);
}
ReactDOM.render(
<Spa/>,
document.getElementById('root')
);
and this is my products.js
const ctx = React.useContext(UserContext);
ctx.users.push(Math.random().toString(36).substr(2, 5));
return (
<div>
<h3>Products Component</h3>
<p>List of the the product we make</p>
{JSON.stringify(ctx.users)}
</div>
);
}
my problem is that when I do click on the products menu the fist time the random works, but if I do again doesn't works, I have to change of link, for example login and return again to products for random works.
Someone knows what could be the problem?
I am using React-dom-16.8 History-5 React-Router-dom-6
ctx.users.push(Math.random().toString(36).substr(2, 5)); is an unintentional side-effect and also won't trigger a rerender. You only see the mutation after navigating away and back to "/products".users should reside in some react state so when it's updated it can trigger React components to rerender. Pass the users state and the state updater (or some callback to update state) as the UserContext value.useEffect to help trigger the effect to update the users state.Spa
const Spa = () => {
const [users, setUsers] = useState(["peter"]);
return (
<Router>
<div>
<h1>Routing - Hello World</h1>
<Link to="/">Home</Link> --
<Link to="/about/">About</Link> --
<Link
to="/products"
state={{ value: Math.random() }} // <-- random state to trigger navigation
>
Products
</Link>
<hr />
<UserContext.Provider value={{ users, setUsers }}>
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/about/" element={<About />} />
<Route path="/products/" element={<Products />} />
</Routes>
</UserContext.Provider>
</div>
</Router>
);
};
Products
const Products = () => {
const { state } = useLocation();
const { users, setUsers } = useContext(UserContext);
// "Listen" for updates to route state to trigger effect
useEffect(() => {
setUsers((users) => [...users, Math.random().toString(36).substr(2, 5)]);
}, [state, setUsers]);
return (
<div>
<h3>Products Component</h3>
<p>List of the the product we make</p>
{JSON.stringify(users)}
</div>
);
};
Use BrowserRouter instead of HashRouter