Home > Mobile >  React Redirect Hook Infinte Loop
React Redirect Hook Infinte Loop

Time:01-07

I don't know the reason but if I try use the Navigate Hook to redirect to a specific path when my desktop changes mode, it dives into a sort of "infinite loop " in the browser:

history.ts:633 Throttling navigation to prevent the browser from hanging. See enter image description here

My App.js

import "./App.scss";
import React, { Fragment, useEffect } from "react";
import { useMediaQuery } from "./hooks/MediaQuery"; 
import Desktop from "./Pages/Desktop/Desktop";
import { Route, Routes, Navigate } from "react-router-dom";

function App() {
  return (
    <Fragment>
      <div className="App">
        <Routes>
          <Route
            exact
            path="*"
            element={
              useMediaQuery(750) ? (
                <Desktop replace to="/" />
              ) : (
                <Navigate replace to="/m" />
              )
            }
          />
        </Routes>
      </div>
    </Fragment>
  );
}

export default App;

CodePudding user response:

It seems the issue is an unconditional redirect loop is created in mobile views, from "*" to "/m" which is matched by "*" and the Navigate component is rendered again.

To stop this you might consider moving the redirect into a component lifecycle and only redirect if not already on "/m". Here's a basic implementation using a useEffect hook in the media query hook.

import { useNavigate, useMatch } from "react-router-dom";
import { useEffect } from "react";

const useMediaQueryRedirect = (width) => {
  const navigate = useNavigate();
  const isMobileMatch = useMatch("/m");

  useEffect(() => {
    const checkWidth = () => {
      if (window.innerWidth < width && !isMobileMatch) {
        navigate("/m");
      }
      if (window.innerWidth >= width && isMobileMatch) {
        navigate("/");
      }
    };
    window.addEventListener("resize", checkWidth, { passive: true });
    return () => {
      window.removeEventListener("resize", checkWidth, { passive: true });
    };
  }, [isMobileMatch, navigate, width]);
};

Create a layout route to use the hook and render the appropriate nested routes.

import { Route, Routes, Outlet } from "react-router-dom";

const MediaLayout = () => {
  useMediaQueryRedirect(750);

  return <Outlet />;
};

...

return (
  ...
  <Routes>
    <Route element={<MediaLayout />}>
      <Route path="/*" element={/* Main component routes */} />
      <Route path="/m/*" element={/* Mobile component routes */} />
    </Route>
  </Routes>
  ...
);

Edit react-redirect-hook-infinte-loop

  • Related