import { INCREMENT, ADD_CHILD, REMOVE_CHILD, CREATE_NODE, DELETE_NODE, } from '../actions'; const childIds = (state, action) => { switch (action.type) { case ADD_CHILD: return [...state, action.childId]; case REMOVE_CHILD: return state.filter(id => id !== action.childId); default: return state; } }; const node = (state, action) => { switch (action.type) { case CREATE_NODE: return { id: action.nodeId, counter: 0, childIds: [], }; case INCREMENT: return { ...state, counter: state.counter + 1, }; case ADD_CHILD: case REMOVE_CHILD: return { ...state, childIds: childIds(state.childIds, action), }; default: return state; } }; const getAllDescendantIds = (state, nodeId) => state[nodeId].childIds.reduce( (acc, childId) => [...acc, childId, ...getAllDescendantIds(state, childId)], [], ); const deleteMany = (state, ids) => { state = { ...state, }; ids.forEach(id => delete state[id]); return state; }; export default (state = {}, action) => { const { nodeId } = action; if (typeof nodeId === 'undefined') { return state; } if (action.type === DELETE_NODE) { const descendantIds = getAllDescendantIds(state, nodeId); return deleteMany(state, [nodeId, ...descendantIds]); } return { ...state, [nodeId]: node(state[nodeId], action), }; };