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

React使用受保护路由时触发Cannot read property 'push' of undefined报错如何解决

问题根因
  • Login组件参数接收错误
    你当前的组件入参写法是const Login = ({ submitForm }, props) => {,函数组件的所有属性只会通过第一个参数传递,你这里将第二个参数写为props,实际拿到的props是undefined,自然无法读取history属性触发报错。
  • 异步登录逻辑时序错误
    fetchLogin是异步方法,你现在调用后立刻执行跳转,会出现接口还没返回登录结果就已经触发跳转的逻辑漏洞。
  • 登录状态持久化逻辑缺失
    你当前的Auth类的authenticated属性只存在于运行内存中,用户刷新页面后这个值会重置为false,导致已经登录的用户还要重新登录。
修复代码示例

修复后的Login组件

// 修正参数接收逻辑
const Login = (props) => {
  const [isSubmitted, setIsSubmitted] = useState(false);

  function submitForm() {
    setIsSubmitted(true);
  }
  const { handleChange, values, handleSubmit, errors } = useForm(
    submitForm,
    validate
  );

  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(false);
  const [login, setLogin] = useState(false);

  const fetchLogin = async (email, password) => {
    try {
      setLoading(true);
      const res = await Axios({
          //API CALL
      });
      if (res.status === 200) {
        setLogin(true);
        localStorage.setItem("user-info", JSON.stringify(res));
        // 登录成功后再更新登录状态、触发跳转
        auth.login(() => {
          props.history.push("/admin");
        });
      }
      setLoading(false);
    } catch (err) {
      setError(err.message);
      setLoading(false);
    }
  };

  function loginButton() {
    fetchLogin(values.email, values.password);
  }
  return (
    <form>
    </form>
  );
};

// 如果Route没有自动注入history属性,用withRouter包裹组件即可
// import { withRouter } from 'react-router-dom'
// export default withRouter(Login);
export default Login;

优化后的Auth类

class Auth {
    constructor() {
      // 初始化时从本地存储读取登录状态
      this.authenticated = !!localStorage.getItem("user-info");
    }
  
    login(cb) {
      this.authenticated = true;
      cb();
    }
  
    logout(cb) {
      this.authenticated = false;
      // 登出时清除本地存储的用户信息
      localStorage.removeItem("user-info");
      cb();
    }
  
    isAuthenticated() {
      // 校验时同步判断本地存储状态,避免刷新后状态丢失
      return this.authenticated && !!localStorage.getItem("user-info");
    }
  }
  
export default new Auth();
额外优化建议
  • 如果使用react-router v5及以上版本,可直接在组件内使用useHistory hook获取history实例,不需要依赖props传递:
import { useHistory } from 'react-router-dom';

const Login = () => {
  const history = useHistory();
  // 后续直接调用history.push("/admin")即可
}
  • 404路由可配置为path="*",语义更明确
  • AdminLayout的传参可以直接写component={AdminLayout},不需要额外包一层箭头函数,Route会自动把路由属性传递给组件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 01:15:05