2017-08-29 97 views
0

My Redux狀態存儲一個存儲註釋數組的對象comments。每個comment對象都有一個replies數組。我將父註釋ID和回覆ID都傳遞給我的reducer,意圖從回覆數組中刪除回覆。Redux - 從嵌套在另一個陣列中的陣列中刪除對象

我的頂級評論對象的簡化版本是這樣的:

{ 
    "count": 4, 
    "data": [ 
    { 
     id: 123, 
     text: 'This is a comment', 
     replies: [ 
     { 
      id: 479, 
      text: 'This is a reply', 
     }, 
     { 
      id: 293, 
      text: 'This is another reply', 
     }, 
     ], 
    }, 
    { 
     id: 728, 
     text: 'This is another comment', 
     replies: [ 
     { 
      id: 986, 
      text: 'This is a reply', 
     }, 
     ], 
    }, 
    ], 
    "pageSize": 5, 
    cursor: "", 
} 

這裏是我的減速器出現包裹父評論對象的數組和扁平的答覆(顯然不是期望結果,但我對處理嵌套數組的最佳方式感到不知所措)。

case types.DELETE_REPLY_SUCCESS: { 
    const content = Object.assign({}, state); 
    content.data = content.data.map((comment) => { 
    const newObj = { ...comment }; 
    if (newObj.id === action.parentCommentId) { 
     return newObj.replies.filter(reply => reply.id !== action.replyId); 
    } 
    return newObj; 
    }); 
    return content; 
} 

回答

1

更新嵌套結構在redux中可能非常令人討厭。我建議使用平坦的結構。您可以使用normalizer或手動執行此操作。

然而,如果你需要更新你的現有結構,這些步驟如下:

  1. 找到您想要更改註釋的索引。
  2. 爲評論創建一個新的過濾回覆數組。
  3. 通過用包含新答覆陣列的新評論替換舊評論來創建新數據陣列。
  4. 用新的數據數組創建一個新的狀態對象。

const state = {"count":4,"data":[{"id":123,"text":"This is a comment","replies":[{"id":479,"text":"This is a reply"},{"id":293,"text":"This is another reply"}]},{"id":728,"text":"This is another comment","replies":[{"id":986,"text":"This is a reply"}]}],"pageSize":5,"cursor":""}; 
 

 
const action = { 
 
    parentCommentId: 123, 
 
    replyId: 479 
 
}; 
 

 
const deleteReplySuccess =() => { 
 
    const data = state.data; 
 
    
 
    // find the index of the comment you want to update 
 
    const commentToChangeIndex = data.findIndex(({ id }) => id === action.parentCommentId); 
 
    
 
    // if it doesn't exist return the state 
 
    if(commentToChangeIndex === -1) { 
 
    return state; 
 
    } 
 
    
 
    // get the comment 
 
    const comment = data[commentToChangeIndex]; 
 
    
 
    // create an updated comment with filtered replies array 
 
    const updatedComment = { 
 
    ... comment, 
 
    replies: comment.replies.filter(reply => reply.id !== action.replyId) 
 
    }; 
 

 
    // create a new state using object spread or assign 
 
    return { 
 
    ...state, 
 
    data: [ // create a new data array 
 
     ...data.slice(0, commentToChangeIndex), // the comments before the updated comment 
 
     updatedComment, // the updated comment 
 
     ...data.slice(commentToChangeIndex + 1) // the comments after the updated comment 
 
    ] 
 
    }; 
 
}; 
 

 
console.log(deleteReplySuccess());

1

上面的答案是更直接的,但我想分享我的一些想法。

首先,this Redux中正常化狀態下的鏈接解決了我的一個大問題......處理嵌套數據結構......您的代碼變得非常複雜。 90%的減速器應該非常簡單。 隨着嵌套數據結構,它們變得複雜

儘管標準化程序是一個非常標準化的狀態標準化工具,我建議您首先編寫自己的標準化程序。我從這樣做中學到了很多東西。

什麼是歸一化數據結構?

它是平坦的。它通常是關係型的。

丹·阿布拉莫夫(誰建立了Redux),建議存儲分組數據。所以你的意見成爲一個團體,你的回覆共享另一個。就像在關係數據庫中一樣。每個「組」都有自己的「桌子」。

起初,這似乎與我不直觀,因爲它感覺你正在編寫更多的數據結構。你不是......而且收益非常值得。

所以,你會存儲你的數據是這樣的

{ 
    "comments": { 
    "allIds" : [1,2,3,4], 
    "byId": { 
     1: { 
     replies: [12], 
     comment: "a comment" 
     }, 
     2: { 
     replies: [13], 
     comment: "another comment" 
     }, 
     3: { 
     replies: [14], 
     comment: "one more comment" 
     }, 
     4: { 
     replies: [15], 
     comment: "oh look, a comment" 
     }, 
    } 
    }, 
    "replies" : { 
    "allIds" : [12,13,14,15], 
    "byId": { 
     12: { 
     comments: [1], 
     reply: "a reply" 
     }, 
     13: { 
     comments: [2], 
     reply: "another reply" 
     }, 
     14: { 
     comments: [3], 
     reply: "yet another reply" 
     }, 
     15: { 
     comments: [4], 
     reply: "a reply" 
     } 
    } 
} 

爲什麼大不了的?

這是什麼方式讓生活更輕鬆?首先,如果我們想要顯示評論列表,我們可以通過我們的​​陣列map()並使用第一個參數訪問密鑰以獲取數據。

這意味着我們可以遍歷單個數組而不是通過嵌套對象。

以同樣的方式,並在回答你的問題您可以通過使用filter()代替map()刪除元素。我不會在這裏解釋過濾器,它需要十秒才能找到比我能解釋的任何東西都好的例子。

然後只要確保你遵循了標準的Redux做事的方式。

  1. 使用reducer複製您的數據結構。你的狀態應該沒有數據初始化......這樣你就知道你做對了。

  2. 編寫你的reducer來處理它的特定狀態(comments reducer等)對於我來說,這些通常由switch語句組成,它們返回狀態或返回一個新狀態。

  3. 編寫爲減速器提供所需新數據的操作。 始終遵循JS的一個功能來處理一項工作的原則。行動不應該做很多事情。

注意但是使用中間件喜歡的thunk,動作可調度這可能會導致邏輯迷死其他行動!

的評論刪除操作可能看起來那樣簡單

function deleteComment(commentId) { 
    return { 
    type: "delete project", 
    payload: commentId 
    } 
} 

這給我們所有我們需要的。 通過使用我們的reducer中前面提到的switch語句,我們可以檢查看到哪些type行動正在分派。 (這告訴我們如何處理提供的數據)以及要刪除的元素,即有效載荷。

您可以按照這種簡單的方法處理85%的應用程序需求。

我知道還有很多Redux比這個更多,但這種方法確實幫助我瞭解如何查看Redux以及如何管理和操縱狀態。 我強烈推薦通過上面鏈接的Dan Abramov的整個eggheads.io教程。他在解釋幾乎所有細節方面做得非常出色。

我希望你的簡短問題的這個長答案有所幫助。