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

react-router中navigate(-1)为何回退两个页面?求排查思路

问题原因分析

导致页面回退两次的核心原因有两个:

  1. 渲染阶段直接修改状态
    你在组件函数体中直接执行if (state === 'init') setState('goBack');,这属于在React的渲染阶段触发状态更新。React要求渲染阶段的代码必须是纯函数式的,不能包含修改状态这类副作用,否则会触发额外的、不可控的重新渲染。

  2. 开发环境Strict Mode的双重渲染机制
    React开发环境默认开启Strict Mode,它会刻意重复调用组件函数、useEffect回调等方法,用于检测潜在的副作用问题。结合上面的错误写法,会出现以下流程:

    • 第一次渲染:state为init,调用setState('goBack')触发重渲染
    • Strict Mode强制第二次渲染:此时state仍为init(第一次状态更新未完成或Strict Mode重置了初始渲染状态),再次调用setState('goBack')
    • 两次状态更新会触发useEffect执行两次,每次都调用navigate(-1),最终导致页面回退两次
修复方案

方案1:移除冗余状态,直接在useEffect中执行回退

如果逻辑仅为无权限时回退上一页,不需要中间状态变量,直接在useEffect中处理即可:

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

const GoBack = () => {
  const navigate = useNavigate();

  useEffect(() => {
    // 此处可添加权限校验逻辑,比如检查用户角色、token有效性等
    navigate(-1);
  }, [navigate]);

  return <p>You are not permitted to view this page</p>;
};

export default GoBack;

方案2:保留状态但将状态更新移到useEffect中

如果确实需要状态控制流程,必须将状态更新操作放到useEffect(副作用阶段)中,避免渲染阶段的副作用:

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

const GoBack = () => {
  const navigate = useNavigate();
  const [state, setState] = useState('init');

  useEffect(() => {
    if (state === 'init') {
      setState('goBack');
    }
  }, [state]);

  useEffect(() => {
    if (state === 'goBack') {
      navigate(-1);
    }
  }, [state, navigate]);

  return <p>You are not permitted to view this page</p>;
};

export default GoBack;
关键注意事项
  • 永远不要在组件的渲染阶段(函数体直接执行的代码)修改状态、调用导航或其他副作用操作,这些操作必须放到useEffect、事件回调等副作用阶段执行。
  • 开发环境的Strict Mode是用来提前发现问题的,生产环境会自动关闭,但开发阶段的错误写法必须修正,避免出现不可预期的行为。

内容的提问来源于stack exchange,提问作者Joseph Beuys' Mum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:16:21