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

useReducer状态在React路由切换时被重新初始化问题求助

问题分析与解决方案

问题根源

  1. 组件挂载触发状态重置:Test 组件每次通过路由切换进入时都会重新挂载,组件内部的 useReducer 会重新执行,将状态初始化为 initialState(count:0),这是状态每次重置的直接原因。
  2. 状态作用域完全独立:ProtectedRoutes 中虽然调用了同一个 Reducer,但它的状态和 Test 组件的状态是两个完全独立的实例,互相不共享,所以前者的状态变化不会影响后者。

解决方案

方案1:将状态提升到共享层级(推荐)

如果需要在路由切换时保留状态,或者要在多个组件间共享状态,把 useReducer 提升到路由的父组件(比如 ProtectedRoutes),通过路由的 Outlet 上下文传递状态和 dispatch:

修改 ProtectedRoutes 组件

import React from 'react'
import { Navigate, useLocation, Outlet } from 'react-router-dom';
import { useAuth } from '../Context/authContext'
import Header from './../Components/Header'
import { Reducer, initialState } from "./../Components/Test/Reducer";

export const ProtectedRoutes = () => {
  const [state, dispatch] = React.useReducer(Reducer, initialState);

  console.log(state, "ProtectedRoutes ")

  const auth = useAuth();
  const location = useLocation()
  if (auth.user && auth.user.role !== 'admin') {
    return <Navigate to='/' state={{ path: location.pathname }} />
  }
  // 通过Outlet上下文传递状态和dispatch给子路由组件
  return (
    <div>
      <Header />
      <Outlet context={{ reducerState: state, reducerDispatch: dispatch }} />
    </div>
  )
}

修改 Test 组件

import React from 'react'
import { useOutletContext } from 'react-router-dom';

export default function Test() {
    // 从父路由的Outlet获取共享的状态和dispatch
    const { reducerState: state, reducerDispatch: dispatch } = useOutletContext();

    console.log(state, "state -----")

    React.useEffect(() => {
        // 仅在状态为初始值时触发更新,避免重复执行
        if (state.count === 0) {
            dispatch({ type: "FETCH_SUCCESS", payload: '' });
        }
    }, [state, dispatch])

    return (
        <div>index</div>
    )
}

方案2:状态持久化(适合组件私有状态)

如果只是 Test 组件自己的状态需要在路由切换后保留,可以将状态持久化到 localStorage,初始化时读取本地存储的值:

修改 Test 组件

import React from 'react'
import { Reducer, initialState } from "./Reducer";

// 从localStorage读取初始化状态,没有则用默认值
const getInitialState = () => {
  const savedState = localStorage.getItem('testReducerState');
  return savedState ? JSON.parse(savedState) : initialState;
}

export default function Test() {
    const [state, dispatch] = React.useReducer(Reducer, getInitialState());

    // 状态变化时同步到localStorage
    React.useEffect(() => {
        localStorage.setItem('testReducerState', JSON.stringify(state));
    }, [state])

    React.useEffect(() => {
        if (state.count === 0) {
            dispatch({ type: "FETCH_SUCCESS", payload: '' });
        }
    }, [state, dispatch])

    console.log(state, "state -----")

    return (
        <div>index</div>
    )
}

注意事项

  • 方案1适合跨组件共享状态的场景,父组件在路由切换时不会卸载,因此状态不会丢失。
  • 方案2适合组件私有状态的持久化,注意敏感数据不要存入 localStorage,避免安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:35:30