想象一下带有两个React组件的UI:
<FilterContainer />
<UserListContainer />
我们从服务器中拉下一组用户:
[
{
name: 'John',
enjoys: ['Sailing', 'Running']
},
{
name: 'Bob',
enjoys: ['Running', 'Eating']
},
{
name: 'Frank',
enjoys: ['Sailing', 'Eating']
}
]
用户界面看起来有点像这样:
过滤:航行正在进行饮食
的UserList:
约翰
谢
您可以点击过滤器或用户。为了进入这个阶段,我们点击了'Sailing'然后点击了'Frank'(也许我们在屏幕中间看到了一张漂亮的Frank照片)。
使用combineReducers
构建的My Redux状态如下所示:
{
ui: {
filter: {enjoys: 'Sailing'},
userList: {selected: 'John'}
}
data: [user array]
}
我有两项行动,SELECT_USER
和SELECT_FILTER
。
当我点击过滤器(SELECT_FILTER
触发)时,如果该用户仍在过滤器中,我希望ui.userList.selected
保持不变,并且ui.userList.selected
设置为null用户不在过滤器中。
因此,如果我现在点击“吃”,我会在其中看到包含Bob和 Frank 的列表,并选择Frank。但如果我点击Running,我会看到John和Bob,但都没有被选中。
然而,我在传统的Redux方法中努力做到这一点。当userList
缩减器看到SELECT_FILTER
操作时,它无法检查data
状态以查看当前所选用户是否仍处于该过滤条件中。
这样做的正确方法是什么?
function filter(state = {enjoys: null}, action) {
switch (action.type) {
case SELECT_FILTER:
return {
...state,
enjoys: action.enjoys
}
default:
return state
}
}
function userList(state = {selected: null}, action) {
switch (action.type) {
case SELECT_USER:
return {
...state,
selected: action.name
}
default:
return state
}
}
const ui = combineReducers({
filter,
userList
})
let initialUsers = [
{
name: 'John',
enjoys: ['Sailing', 'Running']
},
{
name: 'Bob',
enjoys: ['Running', 'Eating']
},
{
name: 'Frank',
enjoys: ['Sailing', 'Eating']
}
]
const rootReducer = combineReducers({
ui,
data: (state=initialUsers) => state // in reality, loaded from server
})
export default rootReducer
答案 0 :(得分:2)
减速器应该只知道一小部分状态。
描述逻辑的好地方是动作创建者。使用redux-thunk,您将能够根据全局状态做出决定。
function selectFilter(enjoys) {
return (dispatch, getState) => {
dispatch({type: SELECT_FILTER, enjoys});
// if getState().ui.userList.selected exists in getState().data
dispatch({type: SELECT_USER, name: null});
}
};
答案 1 :(得分:1)
你需要另外采取行动。
如果您要过滤数据缩减器中的用户,则需要在其中一个组件中调度操作&#39;当您检测到用户数组已更改时,挂钩(componentWillUpdate或componentWillReceiveProps)。此操作将为您的过滤器减速器提供当前用户数组,您可以根据需要设置所选字段。
如果您正在过滤服务器中的用户,我猜您已经有一个可以用于此的动作,如FETCH_USERS_SUCCESS。
答案 2 :(得分:0)
应该由过滤器减速器处理。您需要将用户数据作为操作有效内容的一部分发送。因此,reducer可以对所选用户逻辑进行计算。您应该考虑添加新操作,如@cuttals建议的那样。