【问题标题】:Updating array value inside array of objects更新对象数组内的数组值
【发布时间】:2024-01-30 06:05:01
【问题描述】:

我有一个这样的对象数组“电影”:

{
 id: "some id",
 title: "some title",
 actors: []
}

如您所见,演员数组保持为空,因为我在添加电影时没有添加演员。我想稍后添加演员,同时在 http://localhost:3000/movies/<movieId> 上。 我通过这个表格做到这一点。我只是从现有的演员列表中选择一个演员。

const PostForm = ({ addActorToMovie, movie, actors, history }, props) => {
  const handleSubmit = (values) => {
    addActorToMovie(values);
    // history.push(`/movies/${movie.id}`);
  };
  let actorsList =
    actors.length > 0 &&
    actors.map((item, i) => {
      return (
        <option value={`${item.firstName}, ${item.lastName}`}>
          {item.firstName + item.lastName}{" "}
        </option>
      );
    });

  return (
    <div>
      <h3>Add Actor</h3>
      <Formik
        initialValues={{
          actor: "",
        }}
        onSubmit={(values) => handleSubmit(values)}
        enableReinitialize={true}
      >
        <Form>
          <Field name="actor" component="select">
            <option value="null"> </option>
            {actorsList}
          </Field>
          <button type="submit">Zatwierdz</button>
        </Form>
      </Formik>
    </div>
  );
};

const mapStateToProps = (state, props) => {
  return {
    movie: state.movie,
    actors: state.actors,
  };
};

const mapDispatchToProps = {
  addActorToMovie,
};

export default withRouter(
  connect(mapStateToProps, mapDispatchToProps)(PostForm)
);

表格有效。虽然不是为我的actors array 增加价值。它在 movies 数组下创建一个新对象,如下所示:

actors: {actor: 'Some actor name'}

我的减速器看起来像这样。可能这是问题的根源,但我真的不知道该怎么做。

export const movieReducer = (state = [], action) => {
  switch (action.type) {
    case "MOVIE_ADD":
      return [...state, action.payload];
    case "MOVIE_DELETE":
      return [...state.filter((el) => el.id !== action.payload.id)];
    case "MOVIEACTOR_ADD":
      return {
        ...state,
        actors: action.payload
      };
    default:
      return state;
  }
};

我要做的当然是将我在Formik 中输入的演员推送到指定电影的数组中。

【问题讨论】:

  • 你提到了一个 movies 数组,我们需要查看 reducer 中的状态形状才能正确复制 movies 数组,在这种情况下,ADD_ACTOR_TO_MOVIE 应该包含它正在向哪个电影添加演员。我们还应该看到正在调度操作的 UI 组件。

标签: reactjs redux react-redux


【解决方案1】:

您希望将其附加到现有的 actors 数组中,而不是声明一个仅作为有效负载的新 actors 属性。但是,您首先需要知道您正在更新哪个电影对象,因此这也需要在动作负载中发送。

更新提交处理程序以发送电影 ID 和要添加的演员。

const handleSubmit = ({ actor }) => {
  addActorToMovie({
    movieId: movie.id,
    actor,
  });
};

更新reducer case以映射电影数组,在movieReducer中显示为state。浅拷贝电影state数组,对于匹配的电影id,浅拷贝并追加演员到演员数组。

case "MOVIE_ACTOR_ADD":
  const { actor, movieId } = action.payload;
  return state.map(movie => movie.id === movieId
    ? {
      ...movie,          // <-- shallow copy movie object
      actors: [
        ...movie.actors, // <-- shallow copy existing array
        actor            // <-- append new actor payload
      ],
    }
    : movie
  );

将电影添加到状态时,请确保 actors 数组属性存在。如果您没有将MOVIE_ADD 动作负载传递给它,那么在添加电影时在reducer 中处理它。

case "MOVIE_ADD":
  return [
    ...state,
    { ...action.payload, actors: [] },
  ];

【讨论】:

  • 警告:从 submitForm() 捕获到未处理的错误 TypeError: state.actors is not iterable.
  • 好吧,我相信你的答案是正确的,但似乎我在其他地方也有错误
  • 谢谢,我不相信您会在我提供的少量数据中找到有效的答案。泰!