[英]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:我认为正在发生的事情是这样的:
/
renders triggering the Redirect to /home
/
呈现触发重定向到/home
/
to the history again /
推送到历史记录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.