2016-06-23 1 views
0

Итак, внутри моего редуктора у меня есть массив объектов, называемый «todos», а объект «todos» имеет состояние, которое также является массивом объектов, называемых «комментариями». И внутри каждого из массива «comments» я хотел бы определить состояние строки «commentText», но я не могу понять, как это сделать. Любая помощь будет принята с благодарностью.Как вы определяете состояние объекта внутри массива массива в редукторе (ReactJS + Redux)?

Ниже приведен пример того, что я хотел бы достичь:

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 

NEW EDIT **:

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] 
    } 
    }) 
+0

[Updeep] (https://github.com/substantial/updeep) упрощает выполнение обновлений вложенных объектов и массивов; Я бы рекомендовал взглянуть на него. –

+0

http://stackoverflow.com/questions/37980109/react-redux-complex-deep-state-objects duplicate – xiaofan2406

+0

@ xiaofan2406 Я проверил его, но я не могу понять концепцию достаточно хорошо. Если вы не можете привести пример в соответствии с тем, что я представил? Спасибо –

ответ

0

Это звучит как большой прецедентом для метода .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 
     } 
    ] 
    } 
]; 

При обновлении комментарий, вы должны были бы пройти в todoId и commentId, чтобы вы знали, что искать. При добавлении комментария, вам нужно только пройти в 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, что дает Todo уникальный идентификатор, метки времени, и добавляет пустой 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 
    } 
    }; 
}; 

Это непроверено, но, надеюсь, дает вам представление.

+0

Спасибо за руководство! Пытаюсь все еще обнять вокруг себя голову. Просто чтобы уточнить, как определить полезную нагрузку в создателях действий? –

+0

Кроме того, я хотел бы просто создать пустой массив «comments» в «ADD_TODO» и не устанавливать значения внутри, а когда UPDATE_COMMENT активирован, сможете продолжить добавление нового комментария в инициализированный пустой массив «comments». –

+0

Я обновил исходное сообщение с кодом под NEW EDIT. –