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

使用axios+useReducer/Context/Provider时,todo无法获取initialState值的问题

问题原因与解决方案

对,你猜的没错——useReducer仅在组件首次渲染时读取第二个参数作为初始状态。后续setInitialState更新initialState导致组件重渲染,但useReducer不会用新的initialState去更新todo状态,所以todo始终停留在初始的空数组。

方式一:直接在请求成功后dispatch初始化action(推荐)

去掉中间的initialState状态,直接把请求到的数据通过dispatch传给reducer,逻辑更简洁,减少状态冗余:

export function TodoProvider({children}){
  const apiUrl = "http://localhost:3001/home";

  // 初始化todo为空数组
  const [todo, dispatch] = useReducer(todoReducer, []);

  useEffect(()=>{
    axios.get(apiUrl)
      .then((response)=>{
          // 向reducer发送初始化action
          dispatch({ type: 'INIT_TODOS', payload: response.data.data });
      })
      .catch(e=>console.log(e))
  },[]);

  return (
      <TodoContext.Provider value={todo}>
        <TodoDispatchContext.Provider value={dispatch}>
            {children}
        </TodoDispatchContext.Provider>
      </TodoContext.Provider>
    )
}

对应的reducer需要处理INIT_TODOS动作:

function todoReducer(state, action) {
  switch(action.type) {
    case 'INIT_TODOS':
      // 直接将状态替换为请求到的todo数据
      return action.payload;
    // 其他动作处理(比如新增、删除todo)
    default:
      return state;
  }
}

方式二:监听initialState变化,触发dispatch更新

如果需要保留initialState状态,可以通过额外的useEffect监听它的变化,当数据加载完成后,再dispatch更新todo:

export function TodoProvider({children}){
  const apiUrl = "http://localhost:3001/home";

  const [initialState,setInitialState] = useState([]);
  const [todo, dispatch] = useReducer(todoReducer, initialState);

  useEffect(()=>{
    axios.get(apiUrl)
      .then((response)=>{
          setInitialState(response.data.data);
      })
      .catch(e=>console.log(e))
  },[]);

  // 当initialState有数据时,更新todo状态
  useEffect(() => {
    // 避免初始空数组时触发
    if (initialState.length > 0) {
      dispatch({ type: 'INIT_TODOS', payload: initialState });
    }
  }, [initialState]);

  return (
      <TodoContext.Provider value={todo}>
        <TodoDispatchContext.Provider value={dispatch}>
            {children}
        </TodoDispatchContext.Provider>
      </TodoContext.Provider>
    )
}

关键提醒

React的useReducer和useState一样,初始值仅在组件第一次渲染时生效。后续状态的更新必须通过dispatch(useReducer)或setXxx(useState)来触发,不能依赖初始值变量的更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 16:05:32