You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router页面离开回调问题:props.router未定义解决方案求助

嘿,我来帮你搞定这个路由离开监听的问题!

首先得说清楚:你用的this.props.router.setRouteLeaveHook是react-router v3及更早版本的写法,而你现在用的是react-router-dom v4,这个版本已经完全重构了路由体系,原来的router prop和setRouteLeaveHook方法都被移除了,所以才会报this.props.router is undefined的错误。

不用慌,v4里有更简洁的方式实现页面离开监听,而且完全不需要用React.createClass,下面给你针对类组件的解决方案(符合你当前的技术栈):

解决方案:使用withRouter高阶组件 + history.block

  1. 首先导入withRouter:
import { withRouter } from 'react-router-dom';
  1. 在你的类组件里,通过componentDidMount注册离开钩子,同时在componentWillUnmount里清理(避免内存泄漏):
class YourComponent extends React.Component {
  componentDidMount() {
    // 注册路由离开拦截
    this.unblock = this.props.history.block((location, action) => {
      // 这里写你的业务判断,比如检查是否有未保存的内容
      if (this.state.hasUnsavedChanges) {
        // 返回字符串会触发浏览器的确认弹窗,用户确认后才会离开
        return '你还有未保存的修改,确定要离开当前页面吗?';
      }
      // 如果不需要拦截,返回true或者直接省略即可(允许导航)
    });
  }

  componentWillUnmount() {
    // 组件卸载时清理钩子
    if (this.unblock) {
      this.unblock();
    }
  }

  render() {
    return (
      // 你的组件内容
      <div>...</div>
    );
  }
}

// 一定要用withRouter包裹组件,这样才能拿到history prop
export default withRouter(YourComponent);

关键说明:

  • withRouter会把路由相关的history、location、match props注入到你的组件中,这是v4里获取路由上下文的标准方式。
  • history.block方法是v4里用来拦截路由导航的API,它接受一个回调函数:
    • 回调函数的参数location是要跳转到的目标路由,action是导航类型(比如PUSH、POP)。
    • 如果返回字符串,浏览器会弹出确认对话框,用户点击“确定”才会继续导航,点击“取消”则留在当前页。
    • 如果返回false,会直接阻止导航;返回true则允许导航。
  • 不要在componentWillMount里注册钩子:这个生命周期在React 16.3+已经被标记为不安全,而且在服务端渲染时可能会因为没有history对象报错,改用componentDidMount更安全。

额外:如果是函数组件的写法(供参考)

如果你以后换成函数组件,可以用useHistory钩子:

import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';

function YourComponent() {
  const history = useHistory();

  useEffect(() => {
    const unblock = history.block((location, action) => {
      if (/* 你的判断条件 */) {
        return '确定要离开吗?';
      }
    });

    // 组件卸载时清理钩子
    return () => unblock();
  }, []);

  return <div>...</div>;
}

最后要确认你的整个应用已经被BrowserRouter(或HashRouter)包裹了,比如你的root.jsx里应该有类似这样的代码:

import { BrowserRouter as Router } from 'react-router-dom';

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById('root')
);

内容的提问来源于stack exchange,提问作者Xero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:36:45