1

I know about the navigate hook but I need to control the route from window object that means it has to be a global function. In vuejs, it was easy like,

window.pushpath = function(path) { router.push("/"+path) }

how can i achieve this kind of behaviour in react? I cant use react hooks in js as it is forbidden to use react hooks without using it inside component.

  • Does this help answer your question? https://stackoverflow.com/a/70000286/8690857 Once the solution is implemented you'll have a `history` object that can be used *outside* the React code. – Drew Reese Aug 15 '22 at 05:49
  • I don't think there is something like that in react router, but could you be more specific why are you using that? There could be some workaround of using that – Leo Odishvili Aug 15 '22 at 05:49
  • Can you provide a solid use case for needing this function to be global on the `window` object? – Drew Reese Aug 15 '22 at 05:55
  • Why can't you use a functional component? – GROVER. Aug 15 '22 at 06:22

1 Answers1

0

A trivial solution could be to use a useEffect hook to set the window.pushpath function using the navigate function returned from the useNavigate hook.

Example:

import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

...

const navigate = useNavigate();

useEffect(() => {
  window.pushpath = function(path, options) {
    navigate(path, options);
  }
}, []);

This logic can only work so long as there is a router component higher in the ReactTree than the component running this effect, i.e. the Router must be in the parent component or higher.

Any linters may also complain about a missing dependency on the navigate function. It is, AFAIK, a stable reference, but should be ok to add.

useEffect(() => {
  window.pushpath = function(path, options) {
    navigate(path, options);
  }
}, [navigate]);

Now that window.pushpath is updated, it can be called and passed the same arguments as the navigate function.

navigate

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: any }
  ): void;
  (delta: number): void;
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • I don't know how the internals of react-router works, but it seem like adding `navigate` to the dependency array is a safer option. I doubt it would ever do any harm, and in the case the function returned by useNavigate actually has some state it would be required to avoid subtle bugs if I'm not mistaken. – super Aug 15 '22 at 06:12
  • @super You are correct that `navigate` is an external dependency and could be include, but AFAIK it's a stable reference and likely ok to omit. Not sure what "state" you are referring to though. – Drew Reese Aug 15 '22 at 06:15
  • I'm only pointing out that without checking the react-router source code you can't really know that. Hence, *in the case* it has state. – super Aug 15 '22 at 06:25
  • @super I've spent a lot of time looking at the `react-router` source code. Each router effectively holds a ref to a single Navigator object. [Here's](https://github.com/remix-run/react-router/blob/main/packages/react-router/lib/components.tsx#L187-L190) where it's set in the base `Router` component. – Drew Reese Aug 15 '22 at 06:34