React+Redux动态路由刷新时短暂显示404页面的解决咨询
这个问题本质是刷新页面时,Redux中的menu数据还没通过API请求获取到,导致Routes组件一开始遍历空数组,生成不了对应路由,路由系统找不到匹配项就先渲染了NotFound页面,等请求完成menu数据更新后才渲染正确路由,所以会出现短暂的跳转闪屏。
下面给你几个实用的解决方案:
方案一:添加加载状态,控制路由渲染时机
这是最常用的方案,通过在Redux中维护加载状态,在数据加载完成前不渲染路由(或显示加载提示),避免NotFound提前出现。
更新Menu Reducer,添加加载状态
在menu的reducer里加入isLoading和error状态,跟踪请求状态:const initialState = { menu: [], isLoading: true, // 初始为加载中 error: null }; const menuReducer = (state = initialState, action) => { switch(action.type) { case 'FETCH_MENU_REQUEST': return {...state, isLoading: true}; case 'FETCH_MENU_SUCCESS': return {...state, isLoading: false, menu: action.payload}; case 'FETCH_MENU_FAILURE': return {...state, isLoading: false, error: action.payload}; default: return state; } };记得同步更新你的action creator,添加
FETCH_MENU_REQUEST和FETCH_MENU_FAILURE的action(如果之前没做的话)。在App.js中根据加载状态控制渲染
从Redux中获取isLoading状态,加载中时显示加载提示,加载完成后再渲染路由:const App = ({ menu, isLoading, fetchMenu }) => { useEffect(() => { fetchMenu(); }, []); // 加载中时显示加载组件,替换成你自己的加载UI也可以 if (isLoading) { return <div className="loading">加载中...</div>; } // 加载完成后渲染完整路由 return ( <div className="app-container"> <Routes menu={menu} /> </div> ); }; // 映射Redux状态到组件props const mapStateToProps = state => ({ menu: state.menu.menu, isLoading: state.menu.isLoading }); export default connect(mapStateToProps, { fetchMenu })(App);
方案二:调整Routes组件,延迟NotFound渲染
如果不想显示加载提示,也可以在Routes组件里判断menu是否加载完成,只有当menu有数据时才渲染所有动态路由和NotFound:
// Routes.js(以React Router v6为例,v5逻辑类似,把<Routes>换成<Switch>) import { Routes as RouterRoutes, Route } from 'react-router-dom'; import NotFound from './NotFound'; import PrivateRoute from './PrivateRoute'; const Routes = ({ menu }) => { // 如果menu为空,暂时不渲染任何路由(或渲染空白) if (!menu || menu.length === 0) { return null; } return ( <RouterRoutes> {/* 遍历生成动态路由 */} {menu.map((item) => ( <PrivateRoute key={item.id} exact path={item.link} parentClass="theme-1" element={selectPage(item.linkText)} // v6用element代替component /> ))} {/* 只有menu加载完成后,才渲染NotFound路由 */} <Route path="*" element={<NotFound />} /> </RouterRoutes> ); }; export default Routes;
这样刷新时,menu为空的阶段不会渲染NotFound,也就不会出现闪屏,等menu加载完成后才会渲染完整路由包括NotFound。
额外提示
如果你的项目是React Router v5,注意用<Switch>包裹路由,确保只会匹配第一个符合条件的路由;v6则是用<Routes>组件,逻辑更清晰。
另外,如果API请求很慢,建议给加载状态添加一个友好的加载动画,提升用户体验~
内容的提问来源于stack exchange,提问作者Ixam Deirf

