[Redux] Colocating Selectors with Reducers

Posted Answer1215

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Redux] Colocating Selectors with Reducers相关的知识,希望对你有一定的参考价值。

We will learn how to encapsulate the knowledge about the state shape in the reducer files, so that the components don’t have to rely on it.

 

In current VisibleTodoList.js:

import { connect } from ‘react-redux‘;
import { withRouter } from ‘react-router‘;
import { toggleTodo } from ‘../actions‘;
import TodoList from ‘./TodoList‘;

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case ‘all‘:
      return todos;
    case ‘completed‘:
      return todos.filter(t => t.completed);
    case ‘active‘:
      return todos.filter(t => !t.completed);
    default:
      throw new Error(`Unknown filter: ${filter}.`);
  }
};

const mapStateToProps = (state, { params }) => ({
  todos: getVisibleTodos(state.todos, params.filter || ‘all‘),
});

const VisibleTodoList = withRouter(connect(
  mapStateToProps,
  { onTodoClick: toggleTodo }
)(TodoList));

export default VisibleTodoList;

 

Currently, the getVisibleTodos(state.todos), depends on state‘s structure.

 

Move getVisibleTodos to reducer file:

const todo = (state, action) => {
  switch (action.type) {
    case ‘ADD_TODO‘:
      return {
        id: action.id,
        text: action.text,
        completed: false,
      };
    case ‘TOGGLE_TODO‘:
      if (state.id !== action.id) {
        return state;
      }
      return {
        ...state,
        completed: !state.completed,
      };
    default:
      return state;
  }
};

const todos = (state = [{
  id: 0,
  text: "ok",
  completed: false
}], action) => {
  switch (action.type) {
    case ‘ADD_TODO‘:
      return [
        ...state,
        todo(undefined, action),
      ];
    case ‘TOGGLE_TODO‘:
      return state.map(t =>
        todo(t, action)
      );
    default:
      return state;
  }
};

export default todos;


export const getVisibleTodos = (state, filter) => {
  switch (filter) {
    case ‘all‘:
      return state;
    case ‘completed‘:
      return state.filter(t => t.completed);
    case ‘active‘:
      return state.filter(t => !t.completed);
    default:
      throw new Error(`Unknown filter: ${filter}.`);
  }
};

 

Then in the RootReducer, we manage the state:

import { combineReducers } from ‘redux‘;
import todos, * as fromTodos from ‘./todos‘;

const todoApp = combineReducers({
  todos
});

export default todoApp;

export const getVisibleTodos = (state, filter) =>
    fromTodos.getVisibleTodos(state.todos, filter);

 

Use it in VisibleTodoList.js:

import {connect} from ‘react-redux‘;
import {toggleTodo} from ‘../actions‘;
import TodoList from ‘./TodoList‘;
import {withRouter} from ‘react-router‘;
import { getVisibleTodos } from ‘../reducers‘;


const mapStateToProps = (state, {params}) => {
    return {
        todos: getVisibleTodos(state, params.filter || ‘all‘), // if filter is ‘‘ then change to ‘all‘
    };
};

const VisibleTodoList = withRouter(connect(
    mapStateToProps,
    {onTodoClick: toggleTodo}
)(TodoList));

export default VisibleTodoList;

 

以上是关于[Redux] Colocating Selectors with Reducers的主要内容,如果未能解决你的问题,请参考以下文章

Material-UI 和 Redux-form,点击 select 时重新渲染选项,如何防止?

[Redux/Mobx] 举例说明怎么在redux中定义action?

redux-form 中多选的初始值

以编程方式更改 Redux-Form 字段值

如何使用 yield select 管理接受参数的选择器?

Redux-form Material-UI下拉列表未显示下拉列表,选择