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

React reducer状态数组对象更新报错:state.stories.map不是函数

问题:更新state数组内的story对象时出现state.stories.map is not a function错误

场景与错误

我尝试更新state数组中的story对象,流程如下:

  1. 用户提交编辑表单
  2. 执行updateStory函数,更新内容成功保存到API数据库
  3. 将编辑后的story派发给reducer的"story/updated"分支
  4. 触发错误:state.stories.map is not a function

错误信息:

state.stories.map is not a function
TypeError: state.stories.map is not a function

已知需通过map遍历数组更新目标项,但代码不将state.stories识别为数组;同时不确定action.payload的访问方式是否正确(代码未执行到该步骤)。

数据结构说明

  • Stories结构:一维数组,每个元素为包含StoryID、StartDate等字段的story对象
  • payload结构:单个story对象,包含StoryID及更新后的StartDate、EndDate、StoryTitle、StoryText等字段

相关代码

Reducer配置

const initialState = {
  stories: [],
  isLoading: false,
  currentStory: {},
  error: "",
};


function reducer(state, action) {
  switch (action.type) {
    case "loading":
      return { ...state, isLoading: true, error: "" };

    case "stories/loaded":
      return { ...state, isLoading: false, stories: action.payload, error: "" };

    case "story/loaded":
      return {
        ...state,
        isLoading: false,
        currentStory: action.payload,
        error: "",
      };

    case "story/created":
      return {
        ...state,
        isLoading: false,
        //stories: [...state.stories, action.payload],
        currentStory: action.payload,
        error: "",
      };

    case "story/updated":
      return {
        ...state,
        isLoading: false,
        stories: [
          state.stories.map((story) =>
            story.StoryID === action.payload.StoryID
              ? {
                  ...state.stories,
                  StartDate: action.payload.StartDate,
                  EndDate: action.payload.EndDate,
                  StoryTitle: action.payload.StoryTitle,
                  StoryText: action.payload.StoryText,
                }
              : story
          ),
        ],
        currentStory: action.payload,
      };
// etc.

业务函数代码

function StoriesProvider({ children }) {
  const { user } = useAuth();
  const [{ stories, isLoading, currentStory, error }, dispatch] = useReducer(
    reducer,
    initialState
  );

async function updateStory(theStory, StoryID) {
    dispatch({ type: "loading" });
    try {
      const res = await fetch(
        `${BASE_URL}/stories/${StoryID}/${user.UserInfo[0].CustUUID}`,
        {
          method: "PUT",
          body: JSON.stringify(theStory),
          headers: { "Content-Type": "application/json" },
        }
      );

      dispatch({ type: "story/updated", payload: theStory });
    } catch {
      dispatch({
        type: "rejected",
        payload: "There was an error updating story data.",
      });
    }
  }

解决方案

错误原因

  1. stories被错误转为二维数组:story/updated分支中,将map返回的数组额外包裹了一层[],导致state.stories从一维数组变为[[...]],后续操作无法正常执行map。
  2. 更新对象时错误展开整个数组:匹配到目标story时,代码展开了state.stories整个数组,而非单个story对象,导致对象结构混乱。

修复步骤

1. 修正story/updated分支逻辑

去掉多余的外层数组包裹,同时正确展开单个story对象:

case "story/updated":
  return {
    ...state,
    isLoading: false,
    // 直接使用map返回的数组,无需额外包裹[]
    stories: state.stories.map((story) =>
      story.StoryID === action.payload.StoryID
        ? {
            // 展开原story对象,再覆盖更新字段
            ...story,
            StartDate: action.payload.StartDate,
            EndDate: action.payload.EndDate,
            StoryTitle: action.payload.StoryTitle,
            StoryText: action.payload.StoryText,
          }
        : story
    ),
    currentStory: action.payload,
  };

2. 确保stories/loaded分支的payload为数组

检查stories/loaded分支中action.payload是否为一维数组,避免state.stories被设置为非数组类型。若API返回嵌套结构,需提取数组部分再赋值。

3. 可选:简化更新逻辑

如果action.payload是完整的story对象,可直接替换原对象,无需逐个字段赋值:

case "story/updated":
  return {
    ...state,
    isLoading: false,
    stories: state.stories.map((story) =>
      story.StoryID === action.payload.StoryID ? action.payload : story
    ),
    currentStory: action.payload,
  };

额外优化建议

在updateStory函数中增加API请求成功判断,避免请求失败时误分发成功action:

async function updateStory(theStory, StoryID) {
  dispatch({ type: "loading" });
  try {
    const res = await fetch(
      `${BASE_URL}/stories/${StoryID}/${user.UserInfo[0].CustUUID}`,
      {
        method: "PUT",
        body: JSON.stringify(theStory),
        headers: { "Content-Type": "application/json" },
      }
    );
    // 确认请求成功再分发action
    if (!res.ok) throw new Error("Update failed");
    dispatch({ type: "story/updated", payload: theStory });
  } catch {
    dispatch({
      type: "rejected",
      payload: "更新故事数据时出错。",
    });
  }
}

内容的提问来源于stack exchange,提问作者Big Fat Designs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:45:07