React中调用useState的setState后history.push无法正常跳转怎么办
问题根因
- 你的
App组件将加载判断放在了BrowserRouter外层,当isLoading被设为true时,整个路由树(包括BrowserRouter、上下文Provider、所有路由组件)都会被直接卸载,仅渲染加载动画。 - 登录提交逻辑中先执行
setIsLoading(true),会立刻触发App重渲染卸载路由结构,此时Login组件也被销毁,后续调用的history实例已经对应被卸载的路由,push操作自然无法生效。即使后续再将isLoading设为false,重新渲染出来的是全新的路由实例,之前的跳转指令已经失效。 - 额外问题:你在
App中解构的setUserContext并未在GetUser自定义Hook中返回,运行时会抛出未定义错误,需要删除该字段。
解决方案
提供两种可直接落地的修改方式:
方案1:将路由和上下文移到最外层,加载判断放在内部
修改App.tsx结构,保证BrowserRouter永远不会被卸载:
// App.tsx function App() { const { user, setUser, isLoading, setIsLoading } = GetUser(); return ( <BrowserRouter> <UserContext.Provider value={{isLoading, user, setUser, setIsLoading}}> {isLoading ? ( <div style={spinnerStyle}> <ClipLoader color="red" loading={isLoading.valueOf()} size={150} /> </div> ) : ( <Switch> <Route exact path="/"> <Login/> </Route> <AuthRoute exact path="/Dashboard" component={Dashboard}></AuthRoute> </Switch> )} </UserContext.Provider> </BrowserRouter> ); }
方案2:全局加载层采用浮层形式,不卸载路由结构
如果需要在页面切换、操作过程中都能展示全局加载,可将加载组件设为固定定位浮层,和路由视图平级共存:
// App.tsx function App() { const { user, setUser, isLoading, setIsLoading } = GetUser(); return ( <BrowserRouter> <UserContext.Provider value={{isLoading, user, setUser, setIsLoading}}> {/* 全局加载浮层,不影响下层路由结构 */} {isLoading && ( <div style={{ ...spinnerStyle, position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh', zIndex: 9999, background: '#fff' }}> <ClipLoader color="red" loading={isLoading.valueOf()} size={150} /> </div> )} <Switch> <Route exact path="/"> <Login/> </Route> <AuthRoute exact path="/Dashboard" component={Dashboard}></AuthRoute> </Switch> </UserContext.Provider> </BrowserRouter> ); }
修改完成后放开Login.tsx中history.push("/Dashboard")的注释即可正常跳转。
内容的提问来源于stack exchange,提问作者santi
相关产品推荐
相关产品推荐

