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

React中如何在reducer内通过定时器更新状态?

你的问题核心有两个:一是在reducer里直接修改了原state对象,二是把setTimeout这种副作用放在了纯函数reducer里,而且定时器里直接改state不会触发组件重渲染。

React的reducer必须是纯函数:不能修改入参的state,所有状态更新都要返回新的对象;也不能包含异步操作、定时器这种副作用,这些逻辑应该放在组件或者自定义Hook里。

解决方案步骤

  1. 给reducer新增一个HIDE_DOCS的action类型,专门用来隐藏提示框
  2. 把定时器逻辑从reducer移到AppProvider的Getdocsaction中,通过dispatch触发状态更新
  3. 修正reducer里直接修改state的问题,所有状态更新都返回新对象

修改后的代码

reducer.js

const reducer = (state, action) => {
  switch(action.type) {
    case 'GET_DOCS': {
      const newPassports = state.oldDocs.filter(doc => doc.passport === true);
      
      if (newPassports.length === 0) {
        // 返回全新状态对象,不修改原state
        return {
          ...state,
          Passports: [],
          Showdocs: true,
          Getdocs: false
        };
      } else {
        return {
          ...state,
          Passports: newPassports,
          Showdocs: true,
          Getdocs: !state.Getdocs
        };
      }
    }
    case 'HIDE_DOCS': {
      return {
        ...state,
        Showdocs: false
      };
    }
    default:
      throw new Error('no matching action type');
  }
};

export default reducer;

context.js

import React, { useContext, useReducer } from 'react'
import reducer from './reducer'

const AppContext = React.createContext()

const initialState = {
  // ...你的其他状态
  Showdocs: false,
  // ...你的其他状态
}

const AppProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState)

  const Getdocsaction = () => {
    dispatch({ type: 'GET_DOCS' });
    
    // 在这里判断是否需要触发隐藏提示框的定时器
    const newPassports = state.oldDocs.filter(doc => doc.passport === true);
    if (newPassports.length === 0) {
      setTimeout(() => {
        dispatch({ type: 'HIDE_DOCS' });
        console.log("setTimeout fired");
      }, 5000);
    }
  }

  return (
    <AppContext.Provider
      value={{
        ...state,
        Getdocsaction
      }}
    >
      {children}
    </AppContext.Provider>
  )
}

export const useGlobalContext = () => {
  return useContext(AppContext)
}

export { AppContext, AppProvider }

关键提醒

React状态是不可变的,永远不要直接修改state对象(比如state.Showdocs = true这种写法),必须通过返回新对象或者dispatch action来更新,否则React检测不到状态变化,不会触发组件重渲染。

研究关键词

  • React useReducer 纯函数规则
  • React 副作用处理
  • useContext + useReducer 异步状态更新
  • React 不可变状态更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:15:37