react-router中navigate(-1)为何回退两个页面?求排查思路
问题原因分析
导致页面回退两次的核心原因有两个:
渲染阶段直接修改状态
你在组件函数体中直接执行if (state === 'init') setState('goBack');,这属于在React的渲染阶段触发状态更新。React要求渲染阶段的代码必须是纯函数式的,不能包含修改状态这类副作用,否则会触发额外的、不可控的重新渲染。开发环境Strict Mode的双重渲染机制
React开发环境默认开启Strict Mode,它会刻意重复调用组件函数、useEffect回调等方法,用于检测潜在的副作用问题。结合上面的错误写法,会出现以下流程:- 第一次渲染:state为
init,调用setState('goBack')触发重渲染 - Strict Mode强制第二次渲染:此时state仍为
init(第一次状态更新未完成或Strict Mode重置了初始渲染状态),再次调用setState('goBack') - 两次状态更新会触发
useEffect执行两次,每次都调用navigate(-1),最终导致页面回退两次
- 第一次渲染:state为
修复方案
方案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
相关产品推荐
相关产品推荐

