【问题标题】:How do you define a state of an object inside an array of an array in a reducer (ReactJS + Redux)?你如何在reducer(ReactJS + Redux)的数组中定义一个对象的状态?
【发布时间】:2016-10-26 10:49:44
【问题描述】:

所以在我的减速器中,我有一个名为“todos”的对象数组,而“todos”的一个对象有一个状态,它也是一个名为“cmets”的对象数组。在每个“cmets”数组中,我想定义一个字符串状态“commentText”,但我似乎不知道该怎么做。任何帮助将不胜感激。

以下是我想要实现的示例:

let todoReducer = function(todos = [], action){
    switch(action.type){
        case 'ADD_TODO':
            return [{
                comments:[{
                    commentText: action.commentText
                }]
            }, ...todos]

        case 'CREATE_COMMENT_ARRAY':
            return [{
                commentText: action.eventValue
            ], ...todos.comments] //Referencing todos.comments as 'comments' array of objects of an object of 'todos' array. Would like to directly update if possible and build up 'comments' array.

       default:
        return todos
    }
}
export default todoReducer

新编辑**:

case 'UPDATE_COMMENT':
  return todos.map(function(todo){
    if(todo.id === action.id){
      //want to add a new a 'comment' object to the todo's 'comments' array
    //Something like the following:
        todo.comments: [{
            commentText: action.commentText
        }, ...todo.comments]
    }
  })

【问题讨论】:

  • Updeep 可以轻松执行嵌套对象和数组的更新;我建议看看它。
  • @xiaofan2406 我检查了它,但我似乎无法很好地掌握这个概念。如果你不可以根据我提供的内容提供一个例子吗?谢谢
  • 您是否尝试更新特定 Todo 的commentText?如果是这样,您可能需要为 Todos 提供唯一 ID,以便您可以过滤它们的列表以找到您需要更新的 ID。否则就无法区分一个 Todo 和另一个。
  • @dannyid 是的,就是这样!如果你不介意,你能举个例子吗?我似乎无法让它工作......

标签: javascript reactjs redux react-jsx react-redux


【解决方案1】:

这听起来像是 .map() Array 方法的一个很好的用例。

假设您的数据如下所示:

var todos = [
  {
    id: 1,
    title: 'Todo 1 Title',
    body: 'Todo 1 Body',
    date: 1425364758,
    comments: [
      {
        id: 1,
        commentorId: 42069,
        text: 'Todo 1, Comment 1 Text',
        date: 1425364758
      },
      {
        id: 2,
        commentorId: 42069,
        text: 'Todo 1, Comment 2 Text',
        date: 1425364758
      },
      {
        id: 3,
        commentorId: 42069,
        text: 'Todo 1, Comment 3 Text',
        date: 1425364758
      }
    ]
  },
  {
    id: 2,
    title: 'Todo 2 Title',
    body: 'Todo 2 Body',
    date: 1425364758,
    comments: [
      {
        id: 1,
        commentorId: 42069,
        text: 'Todo 2, Comment 1 Text',
        date: 1425364758
      }
    ]
  },
  {
    id: 3,
    title: 'Todo 3 Title',
    body: 'Todo 3 Body',
    date: 1425364758,
    comments: [
      {
        id: 1,
        commentorId: 42069,
        text: 'Todo 3, Comment 1 Text',
        date: 1425364758
      },
      {
        id: 2,
        commentorId: 42069,
        text: 'Todo 3, Comment 2 Text',
        date: 1425364758
      }
    ]
  }
];

更新评论时,您需要传入todoIdcommentId,以便知道要查找的内容。添加评论时,您只需传入 todoId 即可知道要更新的待办事项:

const todoReducer = (todos = [], action) => {
  switch(action.type) {
    case 'ADD_TODO':
      return [
        action.todo,
        ...todos
      ];
    case 'ADD_COMMENT':
      const { todoId, comment } = action;

      // Map through all the todos. Returns a new array of todos, including the todo with a new comment
      return todos.map(todo => {
        // Look for the todo to add a comment to
        if (todo.id === todoId) {
          // When the todo to update is found, add a new comment to its `comments` array
          todo.comments.push(comment);
        }
        // Return the todo whether it's been updated or not
        return todo;
      });
    case 'UPDATE_COMMENT':
      const { todoId, commentId, commentText } = action;

      // Map through all the todos. Returns a new array of todos, including the todo with the updated comment
      return todos.map(todo => {
        // First find the todo you want
        if (todo.id === todoId) {
          // Then iterate through its comments
          todo.comments.forEach(comment => {
            // Find the comment you want to update
            if (comment.id === commentId) {
              // and update it
              comment.text = commentText;
            }
          });
        }
        // Return the todo whether it's been updated or not
        return todo;
      });
    default:
      return todos;
  }
};
export default todoReducer;

至于您的有效载荷,您可以随意制作它们,它们将在您的动作创建器中创建。例如,下面是 ADD_TODO 的一个实现,它为待办事项提供一个唯一 ID,为其添加时间戳,并在触发操作之前添加一个空的 comments 数组:

import uuid from 'node-uuid';
const addTodo = ({title, body}) => {
  const id = uuid.v4();
  const date = new Date().getTime();
  return {
    type: 'ADD_TODO',
    todo: {
      id,
      title,
      body,
      date,
      comments: []
    }
  };
};

您的 ADD_COMMENT 动作创建者可能如下所示:

import uuid from 'node-uuid';
const addComment = ({todoId, commentorId, commentText}) => {
  const id = uuid.v4();
  const date = new Date().getTime();
  return {
    type: 'ADD_COMMENT',
    todoId,
    comment: {
      id,
      commentorId,
      date,
      text: commentText
    }
  };
};

这是未经测试的,但希望能给你一个想法。

【讨论】:

  • 感谢您的指导!试图仍然把我的头绕在它周围。只是为了澄清一下,如何在动作创建者中定义有效负载?
  • 另外,我想只在 'ADD_TODO' 中创建一个 'cmets' 空数组,而不在里面设置值,当激活 UPDATE_COMMENT 时,能够继续向初始化的添加新注释空“cmets”数组。
  • 我在 NEW EDIT 下用代码更新了原始帖子。
  • 只是检查您是否能够查看新评论。
  • 嘿@JoKo,看看我更新的答案。我阐述了一堆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
  • 2019-07-05
  • 2020-11-01
  • 2020-10-13
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多