10 redux Reducer 重构

如下步骤感受Reducer的重构

初遇 Reducer

最初的reducer看起来如下,如何去重构呢?

const initialState = {
    visibilityFilter : 'SHOW_ALL',
    todos : []
};

function appReducer(state = initialState, action) {
    switch(action.type) {
        case 'SET_VISIBILITY_FILTER' : {
            return Object.assign({}, state, {
                visibilityFilter : action.filter
            });
        }
        case 'ADD_TODO' : {
            return Object.assign({}, state, {
                todos : state.todos.concat({
                    id: action.id,
                    text: action.text,
                    completed: false
                })
            });
        }
        case 'TOGGLE_TODO' : {
            return Object.assign({}, state, {
                todos : state.todos.map(todo => {
                    if (todo.id !== action.id) {
                      return todo;
                    }

                    return Object.assign({}, todo, {
                        completed : !todo.completed
                    })
                  })
            });
        }
        case 'EDIT_TODO' : {
            return Object.assign({}, state, {
                todos : state.todos.map(todo => {
                    if (todo.id !== action.id) {
                      return todo;
                    }

                    return Object.assign({}, todo, {
                        text : action.text
                    })
                  })
            });
        }
        default : return state;
    }
}

提取工具函数

工具函数也叫通用函数,如下我们提取了通用函数

// 更新对象
function updateObject(oldObject, newValues) {
    // 用空对象作为第一个参数传递给 Object.assign,以确保是复制数据,而不是去改变原来的数据
    return Object.assign({}, oldObject, newValues);
}

然后我们的修改我们的reducer,如下Add_TODO的处理流程

case 'ADD_TODO' : {
    const newTodos = state.todos.concat({
        id: action.id,
        text: action.text,
        completed: false
    });
     // todos 发送了改变,所以我们必须更新 todos
    return updateObject(state, {todos : newTodos});
}

提取 case reducer

就是将case内的逻辑放到函数中(学过重构对这步应该比较熟悉吧),如下,我们将ADD_TODO的代码分离为一个新的方法

function addTodo(state, action) {
    const newTodos = state.todos.concat({
        id: action.id,
        text: action.text,
        completed: false
    });

    return updateObject(state, {todos : newTodos});
}

然后修改我们的reducer

case 'ADD_TODO' : 
    return addTodo(state, action);

拆分reducer

经过前面的重构,我们的reducer看起来如下:

function appReducer(state = initialState, action) {
    switch(action.type) {
        case 'SET_VISIBILITY_FILTER' : 
            return setVisibilityFilter(state, action);
        case 'ADD_TODO' : 
            return addTodo(state, action);
        case 'TOGGLE_TODO' : 
            return toggleTodo(state, action);
        case 'EDIT_TODO' : 
            return editTodo(state, action);
        default : return state;
    }
}

现在把它拆分为3个reducer
function visibilityReducer(visibilityState = ‘SHOW_ALL’, action) {
switch(action.type) {
case ‘SET_VISIBILITY_FILTER’ :
return setVisibilityFilter(visibilityState, action);
default :
return visibilityState;
}
};

function todosReducer(todosState = [], action) {
switch(action.type) {
case ‘ADD_TODO’ :
return addTodo(todosState, action);
case ‘TOGGLE_TODO’ :
return toggleTodo(todosState, action);
case ‘EDIT_TODO’ :
return editTodo(todosState, action);
default : return todosState;
}
}

// 根 reducer
function appReducer(state = initialState, action) {
return {
todos : todosReducer(state.todos, action),
visibilityFilter : visibilityReducer(state.visibilityFilter, action)
};
}

通过切片组合 Reducer

使用 Redux 中 combineReducers 这个工具函数去把管理每个 state 切片的逻辑组合起来
即,我们的根reducer如下:

// 根 reducer
function appReducer(state = initialState, action) {
    return {
        todos : todosReducer(state.todos, action),
        visibilityFilter : visibilityReducer(state.visibilityFilter, action)
    };
}

使用combineReducers 代替自己组合

// 顶层 reducer
const appReducer = combineReducers({
    visibilityFilter : visibilityReducer,
    todos : todosReducer
});

最终重构后的reducer

// 可重用的工具函数
function updateObject(oldObject, newValues) {
    // 将空对象作为第一个参数传递给 Object.assign,以确保只是复制数据,而不是去改变数据
    return Object.assign({}, oldObject, newValues);
}

// 可重用的工具函数
function updateItemInArray(array, itemId, updateItemCallback) {
    const updatedItems = array.map(item => {
        if(item.id !== itemId) {
            // 因为我们只想更新一个项目,所以保留所有的其他项目
            return item;
        }

         // 使用提供的回调来创建新的项目
        const updatedItem = updateItemCallback(item);
        return updatedItem;
});

    return updatedItems;
}



// SET_VISIBILITY_FILTER Case 处理方法
function setVisibilityFilter(visibilityState, action) {
    // 从技术上将,我们甚至不关心之前的状态
    return action.filter;
}

// visibility Reducer
function visibilityReducer(visibilityState = 'SHOW_ALL', action) {
    switch(action.type) {
        case 'SET_VISIBILITY_FILTER' : 
            return setVisibilityFilter(visibilityState, action);
        default : 
            return visibilityState;
    }
};



// ADD_TODO Case 处理方法
function addTodo(todosState, action) {
    const newTodos = todosState.concat({
        id: action.id,
        text: action.text,
        completed: false
});

    return newTodos;
}

// TOGGLE_TODO Case 处理方法
function toggleTodo(todosState, action) {
    const newTodos = updateItemInArray(todosState, action.id, todo => {
        return updateObject(todo, {completed : !todo.completed});
});

    return newTodos;
}

// EDIT_TODO Case 处理方法
function editTodo(todosState, action) {
    const newTodos = updateItemInArray(todosState, action.id, todo => {
        return updateObject(todo, {text : action.text});
});

    return newTodos;
}

// todos Reducer
function todosReducer(todosState = [], action) {
    switch(action.type) {
        case 'ADD_TODO' : return addTodo(todosState, action);
        case 'TOGGLE_TODO' : return toggleTodo(todosState, action);
        case 'EDIT_TODO' : return editTodo(todosState, action);
        default : return todosState;
    }
}



// 顶层 reducer
const appReducer = combineReducers({
    visibilityFilter : visibilityReducer,
    todos : todosReducer
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值