history.listen() replacement in react router V6

Viewed 793

I'm upgrading react router V5 application to react router v6. I have come across some snippet which I'm not able to convert to V6. I tried enough and looked at different solutions over internet but nothing seem to work for me.

Code that I want to convert to V6,

import React, { useRef, useEffect } from "react";
import { useHistory } from "react-router-dom"; 

export default () => {
  const ref = useRef(null);
  const history = useHistory(); // the browser history object  
 
  useEffect(() => {
    const { onParentNavigate } = mount(ref.current, {
      onNavigate: ({ pathname: nextPathname }) => {
        const { pathname } = history.location;                 
        if (pathname !== nextPathname) {

          history.push(nextPathname); //<<<<< how to convert this to v6 ?
        }
      },
    });
 
    history.listen(onParentNavigate); //<<<<<< how to convert this to v6 ?
  }, []);
 
  return <div ref={ref} />;
};

MyVersion using V6

const ref = useRef(null);
  //  const navigation = useContext(UNSAFE_NavigationContext).navigator as BrowserHistory();
  const navigate = useNavigate(); // V6
  const location = useLocation(); // V6

  useEffect(() => {
    const { onParentNavigate } = dashboardMount(ref.current, {

      onNavigate: (result: any) => {
        const { pathname } = location;
        if (pathname !== result.location.pathname) {

          navigate(result.location.pathname, { replace: true }); // This is not throwing any error but not giving expected outcome

        }
      }
    })

    navigate(onParentNavigate); // This not throwing any error but not giving me expected outcome as well

  }, []);

  return <div ref={ref}></div>

Any pointer or solution will be highly appreciated !

1 Answers

You could likely use the UNSAFE_NavigationContext exported from react-router-dom to access the raw "history" navigator object.

///////////////////////////////////////////////////////////////////////////////
// DANGER! PLEASE READ ME!
// We provide these exports as an escape hatch in the event that you need any
// routing data that we don't provide an explicit API for. With that said, we
// want to cover your use case if we can, so if you feel the need to use these
// we want to hear from you. Let us know what you're building and we'll do our
// best to make sure we can support you!
//
// We consider these exports an implementation detail and do not guarantee
// against any breaking changes, regardless of the semver release. Use with
// extreme caution and only if you understand the consequences. Godspeed.
///////////////////////////////////////////////////////////////////////////////

/** @internal */
export {
  UNSAFE_NavigationContext,
  UNSAFE_LocationContext,
  UNSAFE_RouteContext,
} from "react-router";

Example:

import React, { useContext, useRef, useEffect } from "react";
import { UNSAFE_NavigationContext } from "react-router-dom";

export default () => {
  const ref = useRef(null);
  const { navigator } = useContext(UNSAFE_NavigationContext); // the browser history object  
 
  useEffect(() => {
    const { onParentNavigate } = mount(ref.current, {
      onNavigate: ({ pathname: nextPathname }) => {
        const { pathname } = navigator.location;                 
        if (pathname !== nextPathname) {

          navigator.push(nextPathname);
        }
      },
    });
 
    const unlisten = navigator.listen(onParentNavigate);

    return unlisten; // <-- cleanup listener on component unmount
  }, []);
 
  return <div ref={ref} />;
};
Related