Well, it turns out you can duplicate the behavior if you implement a custom router that instantiates the history state in the same manner as RRDv6 routers.
Examine the BrowserRouter implementation for example:
export function BrowserRouter({
basename,
children,
window
}: BrowserRouterProps) {
let historyRef = React.useRef<BrowserHistory>();
if (historyRef.current == null) {
historyRef.current = createBrowserHistory({ window });
}
let history = historyRef.current;
let [state, setState] = React.useState({
action: history.action,
location: history.location
});
React.useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
basename={basename}
children={children}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
}
Create a CustomRouter
that consumes a custom history
object and manages the state:
const CustomRouter = ({ history, ...props }) => {
const [state, setState] = useState({
action: history.action,
location: history.location
});
useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
{...props}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
};
This effectively proxies the custom history
object into the Router
and manages the navigation state.
From here you swap in the CustomRouter
with custom history
object for the existing Router
imported from react-router-dom
.
export default function App() {
return (
<CustomRouter history={history}>
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
</Routes>
</div>
</CustomRouter>
);
}
Fork of your codesandbox:
Update
react-router-dom@6
surfaces a history router.
HistoryRouter
<unstable_HistoryRouter>
takes an instance of the history
library as
prop. This allows you to use that instance in non-React contexts or as
a global variable.
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import { createBrowserHistory } from "history";
const history = createBrowserHistory({ window });
ReactDOM.render(
<HistoryRouter history={history}>
{/* The rest of your app goes here */}
</HistoryRouter>,
root
);
There is this note:
This API is currently prefixed as unstable_
because you may
unintentionally add two versions of the history
library to your app,
the one you have added to your package.json and whatever version React
Router uses internally. If it is allowed by your tooling, it's
recommended to not add history
as a direct dependency and instead
rely on the nested dependency from the react-router
package. Once we
have a mechanism to detect mis-matched versions, this API will remove
its unstable_
prefix.
Notes on RRDv6.4+
If you are using RRDv6.4+ and not using the Data routers the good-ish news is that unstable_HistoryRouter
is still being exported through at least RRDv6.7.0. You can follow along the filed issue in the repo here.
If you are using the Data routers then the new "unstable" method is to use an attached navigate
function from the router object directly.
Example:
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter(...);
...
router.navigate(targetPath, options);
navigate
outside of component. And that's exactly what I need – Artillery