React生命周期方法引发问题:无法读取pathname及多次重渲染
解决你的高阶组件重渲染与pathname未定义问题
我来帮你搞定这两个问题,咱们逐个分析并给出修复方案:
1. 解决“无法读取undefined的pathname属性”错误
这个问题的核心是你的高阶组件没有接收到react-router的location props。@connect装饰器默认会屏蔽掉来自react-router的路由相关props,如果你的CheckPermission HOC没有被withRouter包裹,就无法获取到location对象。
修复要点:
- 导入
react-router-dom的withRouter,用它包裹你的高阶组件,确保路由props能被正确注入 - 在访问
pathname之前先做存在性检查,避免空指针错误
2. 解决组件多次重渲染问题
componentWillMount是React已经标记为不安全的生命周期方法,它会在组件挂载前执行,很容易触发不必要的重渲染。更稳妥的做法是用componentDidMount,它只会在组件挂载完成后执行一次,不会引发额外的渲染循环。
另外,你代码里的&是位运算符,应该改成逻辑与&&,这也是个容易忽略的小细节。
修复后的完整代码
import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; // 注意顺序:withRouter要包裹connect后的组件,确保路由props能传递进来 @withRouter @connect(state => state.job, {}) export default function CheckPermission(EnhancedComponent) { return class Redirect extends Component { componentDidMount() { // 先检查location是否存在,再访问pathname if (this.props.location) { this.on_applied_job_route = this.props.location.pathname.includes('applied_job'); } } render() { // 同样先判断location是否存在,同时修正位运算符为逻辑与 if (this.props.location && this.props.has_applied_job && this.on_applied_job_route) { // 这里写你的重定向或权限拦截逻辑 return <Redirect to="/your-target-route" />; } return <EnhancedComponent {...this.props} />; } }; }
额外优化建议(React 16.8+)
如果你的项目已经支持Hook,可以把这个高阶组件改写成函数式风格,写法更简洁,还能彻底避免类组件的生命周期问题:
import { connect } from 'react-redux'; import { withRouter, useLocation, Redirect } from 'react-router-dom'; import { useEffect, useState } from 'react'; const CheckPermission = (EnhancedComponent) => { const WrappedComponent = (props) => { const location = useLocation(); const [onAppliedJobRoute, setOnAppliedJobRoute] = useState(false); // 仅在location.pathname变化时更新状态,避免无效重渲染 useEffect(() => { setOnAppliedJobRoute(location.pathname.includes('applied_job')); }, [location.pathname]); if (props.has_applied_job && onAppliedJobRoute) { return <Redirect to="/your-target-route" />; } return <EnhancedComponent {...props} />; }; return withRouter(connect(state => state.job, {})(WrappedComponent)); }; export default CheckPermission;
内容的提问来源于stack exchange,提问作者Jamie Aden
相关产品推荐
相关产品推荐

