简体   繁体   English

使用 history.push 后 React Router Redirect 不触发

[英]React Router Redirect not firing after history.push used

I am using react-router-dom and I am trying to push to the browser history using the history object from the useHistory hook.我正在使用 react-router-dom,我正在尝试使用useHistory挂钩中的历史记录 object 推送到浏览器历史记录。 The path that I push to should trigger some logic within the router which will force a redirect to another path (which renders some content).我推送的路径应该触发路由器内的一些逻辑,这将强制重定向到另一个路径(呈现一些内容)。

My issue is that the <Redirect /> does not seem to be doing anything and I'm not 100% sure I know why.我的问题是<Redirect />似乎没有做任何事情,我不是 100% 确定我知道为什么。 I created a codepen to demonstrate the issue that I am having.我创建了一个代码笔来演示我遇到的问题。 (Same as code below). (与下面的代码相同)。 You can see the issue if you manually navigate the browser in the codepen to the main route eg https://c629mk.csb.app/ , you will see no content load.如果您在 codepen 中手动将浏览器导航到主要路线,例如https://c629mk.csb.app/ ,您会看到该问题,您将看不到任何内容加载。

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import {
  Route,
  Switch,
  Redirect,
  useHistory,
  BrowserRouter,
  useRouteMatch
} from "react-router-dom";

const HomeRouter = () => {
  const { path } = useRouteMatch();
  const someRouterSpecificLogic = true;
  const initialPath = someRouterSpecificLogic ? "location" : "videos";
  return (
    <Switch>
      <Route path={`${path}/location`} render={() => <h1>Location</h1>} />
      <Route path={`${path}/videos`} render={() => <h1>Videos</h1>} />
      <Redirect from={`${path}/`} to={`${path}/${initialPath}`} />
    </Switch>
  );
};

const AboutRouter = () => {
  const { path } = useRouteMatch();
  return (
    <Switch>
      <Route path={`${path}/history`} render={() => <h1>History</h1>} />
      <Route path={`${path}/background`} render={() => <h1>Background</h1>} />
      <Redirect from={`${path}/`} to={`${path}/history`} />
    </Switch>
  );
};

const useSomeAsyncHook = () => {
  const [asyncResult, setAsyncResult] = useState(false);
  useEffect(() => {
    setTimeout(() => {
      setAsyncResult("someValue");
    }, 300);
  });
  return asyncResult;
};

const AppRouter = () => {
  const history = useHistory();
  const asycnResult = useSomeAsyncHook();

  useEffect(() => {
    if (asycnResult === "someValue") {
      history.push("/home");
    }
  }, [history, asycnResult]);

  return (
    <>
      <p>There should be other content rendering on this page:</p>
      <Switch>
        <Route path="/home" component={HomeRouter} />
        <Route path="/about" component={AboutRouter} />
        <Redirect from="/" to="/home" />
      </Switch>
    </>
  );
};
const App = () => {
  return (
    <BrowserRouter>
      <AppRouter />
    </BrowserRouter>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

What I think is happening is this:我认为正在发生的事情是这样的:

  1. / renders triggering the Redirect to /home /呈现触发重定向到/home
  2. useEffect pushes / to the history again useEffect 再次将/推送到历史记录
  3. Redirect logic does not work the second time around重定向逻辑第二次不起作用

I am wondering if anyone knows how to force the redirect to happen at 3 again?我想知道是否有人知道如何强制重定向再次发生在 3 点?

This can be resolved by adding a loadState to the code.这可以通过在代码中添加 loadState 来解决。 This way the routes / redirect logic only renders after the history.push has taken place.这样,路由/重定向逻辑仅在 history.push 发生后才呈现。

I was confused because I thought that history.push would update the internal state of browserRouter and trigger a rerender of all child routes/ redirects.我很困惑,因为我认为 history.push 会更新 browserRouter 的内部 state 并触发所有子路由/重定向的重新渲染。 This is not the case.不是这种情况。 In my case history.push did not cause the Redirect component to rerender to it did not trigger another redirect and the user would just see a white screen.在我的案例中,history.push 没有导致重定向组件重新呈现给它,也没有触发另一个重定向,用户只会看到一个白屏。 Adding a loadstate as shown below resolved the problem for me:添加如下所示的加载状态为我解决了问题:

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import {
  Route,
  Switch,
  Redirect,
  useHistory,
  BrowserRouter,
  useRouteMatch
} from "react-router-dom";

const HomeRouter = () => {
  const { path } = useRouteMatch();
  const someRouterSpecificLogic = true;
  const initialPath = someRouterSpecificLogic ? "location" : "videos";
  return (
    <Switch>
      <Route path={`${path}/location`} render={() => <h1>Location</h1>} />
      <Route path={`${path}/videos`} render={() => <h1>Videos</h1>} />
      <Redirect from={`${path}/`} to={`${path}/${initialPath}`} />
    </Switch>
  );
};

const AboutRouter = () => {
  const { path } = useRouteMatch();
  return (
    <Switch>
      <Route path={`${path}/history`} render={() => <h1>History</h1>} />
      <Route path={`${path}/background`} render={() => <h1>Background</h1>} />
      <Redirect from={`${path}/`} to={`${path}/history`} />
    </Switch>
  );
};

const useSomeAsyncHook = () => {
  const [asyncResult, setAsyncResult] = useState(false);
  const [asyncResultFetched, setAsyncResultFetched] = useState(false);
  useEffect(() => {
    setTimeout(() => {
      setAsyncResult("someValue");
      setAsyncResultFetched(true);
    }, 300);
  });
  return { asyncResult, asyncResultFetched };
};

const AppRouter = () => {
  const history = useHistory();
  const { asycnResult, asyncResultFetched } = useSomeAsyncHook();

  useEffect(() => {
    if (asycnResult === "someValue") {
      history.push("/home");
    }
  }, [history, asycnResult]);

  if (!asyncResultFetched) {
    return <h1>Loading...</h1>;
  }

  return (
    <>
      <p>There should be other content rendering on this page:</p>
      <Switch>
        <Route path="/home" component={HomeRouter} />
        <Route path="/about" component={AboutRouter} />
        <Redirect from="/" to="/home" />
      </Switch>
    </>
  );
};
const App = () => {
  return (
    <BrowserRouter>
      <AppRouter />
    </BrowserRouter>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

Thank you to @Abdulrahman Ali and @Drew Reese for their assistance in helping me realise what my issue was in the comments of my question above感谢@Abdulrahman Ali 和@Drew Reese 的帮助,帮助我在上面的问题评论中意识到我的问题所在

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM