#8 immutable在redux中的使用,TodoApp

immutable在redux中的应用主要集中在reducers中对state数据的操作上。

可以参考 stackoverflow中的问题

下面和结合一个实例关于immutable部分的介绍和注意的问题。

不使用immutable时的写法

数据结构(普通的对象数据):

const dummyTodos = [
  { id: 0, isDone: true,  text: 'make components' },
  { id: 1, isDone: false, text: 'design actions' },
  { id: 2, isDone: false, text: 'implement reducer' },
  { id: 3, isDone: false, text: 'connect components' }
];   

纯组件:

const Todo = ({ todo }) => {
  if (todo.isDone) {
    return {todo.text}
  }
  return {todo.text}
};

const TodoList = ({ todos }) => {
  return (
    
    {todos.map(todo => (
  • )}
); }

这个todo app有2个主要的动作,'ADD_TODO', 'TOGGLE_TODO',下面来完成action creators,reducers等

action creators, reducers

action creators

// 产生一个随机的32位字符串
const uid = () => Math.randow().toString(34).slice(2);

const addTodo = (text) => ({
  type: 'ADD_TODO',
  payload: {
    id: uid(),
    text,
    isDone: false
  }
});
const toggleTodo = (id) => ({
  type: 'TOGGLE_TODO',
  payload: id 
});

reducers 和 immutable js

在这里就涉及到数据的处理工作了,通过immutable来完成添加和更新数据。(这里actions比较少,直接将所有的actions.type都用一个reducer处理)

// 使用常用的Map, List集合
import { Map, List } from 'immutable';

# 初始化, 将初始状态变为List集合
const initState = List([]);

// 将数据解构变为immutable形式
List [
  Map { id: 0, isDone: true,  text: 'make components' },
  Map {...},
  Map {...}
  ...
]

const rootReducer = (state = initState, action) => {
  switch (action.type) {
    case 'ADD_TODO':
    // 变为immutable之后,可以直接使用 'push' 来添加到数组
    // 不用担心改变原来的数据
      # 注意先将对象变为Map集合之后再push到 List集合中
      return state.push(Map(action.payload));
    case 'TOGGLE_TODO':
     // 对于更新Map集合中的某个属性,使用immutable中update方法 
     // Map集合 update方法的其中一种形式 update(key, updater)
      # 注意这里使用immutable中的'map'和'get'方法: todo.get('id')  
      return state.map(todo => {
        if (todo.get('id') === action.payload) {
          return todo.update('isDone', isDone => !isDone);
        } else {
          return todo;
        }
      });

    default:
      return state;       
  }
}

然后将逻辑写入纯组件中

const TodoList = ({ todos, toggleTodo, addTodo }) => {
    const onSubmit = (e) => {
      const input = e.target;
      const text = input.value;
      # 判断是否为 enter 键
      const isEnterKey = e.which === 13;
      const isLongEnough = text.length > 0;
      if (isEnterKey && isLongEnough) {
        addTodo(text);
        input.value = '';
      }
    };

    const toggleClick = (id) => () => toggleTodo(id);

    return (
      
    {todos.map(todo => (
  • # 注意这里要将Map集合转变为普通JS对象
  • ))}
) }

使用react-redux将状态和组件连接起来

import { connect } from 'react-redux';

const mapStateToProps = (state) => ({
  todos: state
});

const mapDispatchToProps = (dispatch) => ({
  addTodo: text => dispatch(addTodo(text)),
  toggleTodo: id => dispatch(toggleTodo(id))
});

// 这相当于
 dispatch(addTodo(text))}
  toggleTodo={id => dispatch(toggleTodo(id))}
/>

// 使用一个容器
const TodoListContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

将store通过Provider传递下去

import { createStore } from 'redux';
import { Provider } from 'react-redux';

const store = createStore(rootReducer);

ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);

完成!

完整代码 jsbin

你可能感兴趣的:(#8 immutable在redux中的使用,TodoApp)