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

React useReducer添加表格项时异步状态更新异常问题

React useReducer添加表格项后UI不即时更新问题

在React中使用useReducer向表格添加项时,遇到异步状态更新问题:添加新项后,该项已存入状态,但UI无法立即显示,仅在页面刷新后才会展示正确内容。

useReducer配置

import { createContext, useReducer } from "react";

const initialState = {
  achats: [],
};

export const AchatsContext = createContext(initialState);

export const achatsReducer = (state, action) => {
  const { type, payload } = action;

  switch (type) {
    case "SET_ACHATS":
      return {
        achats: payload,
      };
    case "ADD_ACHAT":
      console.log("ADD_ACHAT", state);

      return {
        ...state,
        achats: [payload, ...state.achats],
      };
    case "REMOVE_ACHAT":
      console.log("REMOVE_ACHAT", payload);

      return {
        ...state,
        achats: payload.achats,
      };
    case "UPDATE_ACHAT":
      console.log("UPDATE_ACHAT", payload);

      return {
        ...state,
        achats: payload.achats,
      };
    default:
      return state;
  }
};

export const AchatsContextProvider = ({ children }) => {
  const [state, dispatch] = useReducer(achatsReducer, initialState);

  return (
    <AchatsContext.Provider value={{ ...state, dispatch }}>
      {children}
    </AchatsContext.Provider>
  );
};

异步分发ADD_ACHAT的代码

async function handleSubmit() {
  if (editorRef.current) {
    setMotif(editorRef.current.getContent());
  }

  const randomValue = Math.floor(Math.random() * 4) + 1; // 生成1-4的随机数

  const code = "ACHT-2023-0002";
  const etat = randomValue;

  try {
    const response = await fetch(
      `http://localhost:4000/api/achats/demandes-achats/add`,
      {
        method: "POST",
        body: JSON.stringify({
          date: date,
          motif: motif,
          num_achat: code,
          etat: etat,
        }),
        headers: {
          "Content-Type": "application/json",
        },
      }
    );

    const json = await response.json();

    if (response.ok) {
      dispatch({ type: "ADD_ACHAT", payload: json });
      handleClose();
    }
  } catch (error) {
    // 错误处理
    console.error("Error:", error);

    // 如果有错误响应,打印详情
    if (error.response) {
      console.error("Error response:", error.response.data);
    }
  }
}

可能的原因及解决建议

  • setMotif异步导致的数据不一致:setMotif是React异步状态更新,调用后立刻使用motif变量提交数据,此时motif可能还是旧值。虽然API返回了正确结果,但如果表格渲染依赖的本地状态和context状态不同步,会导致UI不更新。
    解决:直接获取编辑器内容并作为变量使用,跳过状态存储:

    const motifContent = editorRef.current?.getContent();
    // 提交时用motifContent代替motif
    
  • Context订阅组件未正确响应状态变化:如果表格组件使用了React.memo但未正确声明依赖,或者没有通过useContext获取最新的achats状态,会导致组件不重渲染。
    解决:检查表格组件是否正确调用const { achats } = useContext(AchatsContext),若用了memo,确保依赖数组包含achats。

  • API返回数据结构不匹配:确认API返回的json数据结构和现有achats数组中的项结构一致,若字段缺失或格式错误,表格可能无法渲染新项。
    解决:在dispatch前打印json,对比现有achats项的字段,确保结构完全匹配。

  • 表格渲染逻辑存在问题:检查表格组件是否正确遍历achats数组,有没有错误的条件渲染(比如仅当数组长度大于1才显示),或者过滤逻辑错误。
    解决:在表格组件中打印achats,确认状态更新后数组已包含新项,再排查渲染逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:05:54