reducer 측면에서 최소 양의 작업을 필요로한다. 하지만 dispatch 되기 전에 데이터를 state shape에 맞추는 작업을 하기 위해 action creator가 잠재적으로 꽤 많은 양의 작업을 필요로한다. 이것은 아이템을 삭제하는 작업을 처리할 수 없다.
Reducer Composition 자르기
만약 슬라이스 리듀서의 중첩된 트리를 가진다면, 각 슬라이스 리듀서는 action에 응답하는 방식을 알아야한다. 우리는 action에서 관련 데이터를 포함해야한다. comment의 ID를 가진 Post 객체를 업데이트 하고, ID를 키로 이용하여 새로운 Comment 객체를 생성하고 Comment IDs 배열에 해당 코멘트 ID를 포함해야한다.
// actions.js
function addComment(postId, commentText) {
// Generate a unique ID for this comment
const commentId = generateId('comment');
return {
type: 'ADD_COMMENT',
payload: {
postId,
commentId,
commentText
}
};
}
// reducers/posts.js
function addComment(state, action) {
const { payload } = action;
const { postId, commentId } = payload;
// Look up the correct post, to simplify the rest of the code
const post = state[postId];
return {
...state,
// Update our Post object with a new "comments" array
[postId]: {
...post,
// comments 배열에 새로 생성된 코멘트의 commentId를 추가.
comments: post.comments.concat(commentId)
}
};
}
function postsById(state = {}, action) {
switch (action.type) {
case 'ADD_COMMENT':
return addComment(state, action);
default:
return state;
}
}
const postsReducer = combineReducers({
byId: postsById,
allIds: allPosts
});
// reducers/comments.js
function addCommentEntry(state, action) {
const { payload } = action;
const { commentId, commentText } = payload;
// Create our new Comment object
const comment = { id: commentId, text: commentText };
// Insert the new Comment object into the updated lookup table
return {
...state,
[commentId]: comment
};
}
function commentsById(state = {}, action) {
switch (action.type) {
case 'ADD_COMMENT':
return addCommentEntry(state, action);
default:
return state;
}
}
function addCommentId(state, action) {
const { payload } = action;
const { commentId } = payload;
// Just append the new Comment's ID to the list of all IDs
return state.concat(commentId);
}
function allComments(state = [], action) {
switch (action.type) {
case 'ADD_COMMENT':
return addCommentId(state, action);
default:
return state;
}
}
const commentsReducer = combineReducers({
byId: commentsById,
allIds: allComments
});
이 예제는 약간 길다. 왜냐하면 모든 slice reducer와 case reducer가 서로 어떻게 fit해야 하는지를 보여줘야 하기 때문이다. 관련 위임을 주목하자.
postsById slice reducer는 addComment에게 해당 동작을 위임했다. 이것은 해당 Post item에 새로운 comment ID를 추가한다. 반면에, commentById와 allComments 슬라이스 리듀서는 자신의 리듀서를 가진다. 이것은 Comments lookup table과 comment ID 리스트를 업데이트한다.