I'm using context to store a global piece of information which is updated when navigating around the web app from a Link component. For some reason, when I update the context data, I get a "Warning: You cannot change <Router history>" in the console. My data has no history object in it, just a value and a function to update. What could cause this?
Here is my setup:
const AppContext = createContext({
appData: {},
setAppData: () => {},
});
const App = () => {
const [appData, setAppData] = useState({
foo: null,
});
return (
<AppContext.Provider value={[appData, setAppData]}>
<Admin title="My Admin App">
<Resource name="foo" show={ShowFoo} />
</Admin>
</AppContext.Provider>
)
};
My menu has nav links using this component:
export const MyMenuLink = ({ primaryText, to, leftIcon, sidebarIsOpen, onMenuClick, dense, foo }) => {
const clickHandler = (e) => {
const newAppData = {
...appData,
foo: foo,
};
setAppData(newAppData);
};
return (
<Link to={to} onClick={clickHandler}>
<Typography variant="inherit">{primaryText}</Typography>
</Link>
);
};
So when I click on that link, I get the router history warning, but if I remove the setAppData() call in clickHandler, it disappears.
Thanks
<Router history>
This is a message coming from React Router. React router supports different history-objects, but usually you would connect to a BrowserHistory
and allow the browsers to handle and propagate route changes to the router.
IE pressing the browsers forward/backward buttons will trigger a re-render, not a total page refresh.
React-router is also used by React-Admin.
You can pass along a history into the root <Admin />
component.
If you don't set a history, react-admin will create one for you.
Passing in a history is as simple as:
import {createBrowserHistory} from "history";
const history = createBrowserHistory();
const App = ()=>{
return (<Admin
dashboard={Dashboard}
authProvider={authProvider}
dataProvider={dataProvider}
history={history}
/>)
}
React-router doesn't want the history reference to change.
If you attempt to change it, you'll see the warning pop up.
React will re-render child components when something in the parent changes.
In your case, the context will re-render their children whenever a new value is received in the provider. (basically when calling setAppData
)
This will trigger a rerender on your <Admin>
component.
Since we didn't pass in a history, a new one is created and passed to the router. probably here
You will then see the warning from react router.
Passing in your own router would solve that.
You can try it in this sandbox.
If you comment out the the history prop, you will receive warnings again.
There's a link on the dashboard to trigger the re-render.