React Router v4中onChange参数替代方案及TypeScript重载不匹配报错解决
React Router v4 onChange属性报错替代解决方案
报错原因
React Router v4 官方已移除Route组件的onChange属性,因此TypeScript类型校验时无法匹配到对应的属性定义,才会抛出No overload matched this call错误。
可行替代方案
方案1:全局监听history变化(适配你当前的全局登录校验需求)
利用withRouter高阶组件注入的history对象的listen方法监听路由切换,代码实现如下:
import { HashRouter, Switch, Route, withRouter, RouteComponentProps } from 'react-router-dom'; import { useEffect } from 'react'; // 内部路由组件,通过withRouter注入路由相关属性 const RouteContent = (props: RouteComponentProps) => { useEffect(() => { // 初始化执行一次登录校验 const checkAuth = () => { if (!authstore.isLoggedIn && props.location.pathname !== "/login") { authstore.checkLogin(); } }; checkAuth(); // 注册路由变化监听 const unListen = props.history.listen(() => { checkAuth(); }); // 组件卸载时移除监听 return () => unListen(); }, [props.history, props.location.pathname]); return ( <div> <div>Hallo.</div> <Route exact path="/" component={Index} /> <Route path="/login" component={Login} /> <Route path="/deployment/deploymentprojects" component={DeploymentProjectsPageflow} /> <Route path="/deployment/deploymenttypes" component={DeploymentTypesPageflow} /> <Route path="/deployment/sonarqube/qualitygates" component={QualityGatePageflow} /> <Route path="/deployment/sonarqube/qualityprofiles" component={QualityProfilePageflow} /> <Route path="/deployment/sonarqube/projecttags" component={ProjectTagPageflow} /> <Route path="/deployment/dependencies" component={DependenciesTable} /> <Route path="/deployment/rollout/release" component={Release} /> <Route path="/deployment/rollout/patch" component={Patch} /> <Route path="/antd" component={AntdLink} /> <Route path="/kafka" component={KafkaView} /> <Route path="/pageFlow" component={MyPageflow} /> <Route path="/antd/components/:component" render={(parameter) => <AntRouter params={parameter} />} /> <Route path="/antd/:component" render={(parameter) => <AntRouter params={parameter} />} /> </div> ); }; // 用withRouter包裹后可拿到路由属性 const RouteContentWithRouter = withRouter(RouteContent); // 外层路由配置 const AppRouter = () => { return ( <HashRouter> <Switch> <Route path="/" component={RouteContentWithRouter} /> </Switch> </HashRouter> ); };
方案2:封装私有路由组件(更适合权限校验场景)
如果你的核心需求是路由访问权限控制,建议封装专用的私有路由组件,粒度更细更灵活:
import { Route, Redirect, RouteProps } from 'react-router-dom'; // 私有路由Props定义 interface PrivateRouteProps extends RouteProps { component: React.ComponentType<any>; } const PrivateRoute: React.FC<PrivateRouteProps> = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={(routeProps) => { // 已登录直接渲染对应组件 if (authstore.isLoggedIn) { return <Component {...routeProps} />; } // 未登录跳转到登录页,携带原路径方便登录后回跳 return <Redirect to={{ pathname: '/login', state: { from: routeProps.location.pathname } }} /> }} /> ); }; // 使用示例 const AppRouter = () => { return ( <HashRouter> <Switch> {/* 无需登录的公开路由用普通Route */} <Route path="/login" component={Login} /> {/* 需要登录的路由用PrivateRoute */} <PrivateRoute exact path="/" component={Index} /> <PrivateRoute path="/deployment/deploymentprojects" component={DeploymentProjectsPageflow} /> {/* 其他需要权限的路由依次替换为PrivateRoute即可 */} </Switch> </HashRouter> ); };
额外优化提示
你原有代码中component={() => <Index />}的写法会导致组件每次渲染都生成新的实例,触发不必要的重渲染,建议直接传递组件引用,需要传参时改用render属性实现。
内容的提问来源于stack exchange,提问作者Amine Aamer
相关产品推荐
相关产品推荐

