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
CodePudding user response:
Use BrowserRouter
instead of HashRouter
CodePudding user response:
Issues
- Linking to a route with the same path and state/etc is effectively a non-op. It won't trigger a navigation and it won't trigger the routed component to rerender.
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"
.
Solution
users
should reside in some react state so when it's updated it can trigger React components to rerender. Pass theusers
state and the state updater (or some callback to update state) as theUserContext
value.- Pass some "random" state value in the link such that it will trigger the navigation action. Check for state in an
useEffect
to help trigger the effect to update theusers
state.
Suggestions
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>
);
};