如何在redux reducer中使用reselct选择器

时间:2017-08-07 13:07:09

标签: redux reselect

我的应用已经拥有各种容器对象使用的大量选择器。这些非常适合访问州的不同部分,并使重构状态更加容易。

现在我想在我的一些reducer函数中使用我的选择器。问题是在reducer中,state参数引用状态的特定切片,而选择器函数期望使用状态根对象调用。

受控示例:

/* Selectors */
const getTodos = state => state.todos;

const getUncompletedTodos = createSelector(
    [ getTodos ],
    todos => todos.filter(t => !t.completed)
);

/* Reducer */
const todosReducer = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ];
    case 'REMOVE_COMPLETED_TODOS':
      return getUncompletedTodos(state); // <-- this won't work
  }
}

2 个答案:

答案 0 :(得分:8)

您的选择器适用于根状态对象。

假装你可以做

 return getUncompletedTodos({todos: state});

但恕我直言,更好的想法是重用过滤功能

/* Selectors */
const getTodos = state => state.todos;

const filterCompleted = todos => todos.filter(t => !t.completed)

const getUncompletedTodos = createSelector(
    [ getTodos ],
    filterCompleted
);

// inside reducer
case 'REMOVE_COMPLETED_TODOS':
    return filterCompleted(state);

答案 1 :(得分:0)

Yury 的答案有效,但没有利用记忆(见评论)。如果需要,解决方案是只为它需要的状态片编写选择器。

选择器会变成:

const getUncompletedTodos = createSelector(
    [todos => todos], // Not sure if there's a way to skip this redundancy and still take advantage of memoization with reselect.
    todos => todos.filter(t => !t.completed)
);

在reducer中,你可以像这样简单地使用它:

case 'REMOVE_COMPLETED_TODOS':
    return getUncompletedTodos(state);

但是,当在其他地方的根状态上使用选择器时,您可以像这样使用它:

getUncompletedTodos(state.todos)

我看到的唯一缺点是您必须记住使用正确的状态部分调用选择器,当然,如果您正确使用 TypeScript,它会提醒您这一点。

相关问题