用reselect提高数据获取性能

引入

  • 获取当前应该显示的待办事项,就是根据Redux Store状态树上的todos和filter两个字段上的值计算出来。但这个计算过程要遍历todos字段上的数组,当数组比较大的时候,对于TodoList组件的每一次重新渲染都重新计算一遍,就会显得负担过重了。
    在这里插入图片描述

两阶段选择过程

  • 如果Redux Store状态树上代表所有待办事项的todos字段没有变化,而且代表当前过滤器的filter字段也没有变化,那么实在没有必要重新遍历整个todos数组来计算一个新的结果
  • reselect库的工作原理:只要相关状态没有改变,那就直接使用上一次的缓存结果
    // src/todos/selector.js
    import {createSelector} from 'reselect';
    import {FilterTypes} from '../constants.js';
    
    /**
     * 从输入参数state抽取第一层结果,将这第一层结果和之前抽取的第一层结果做比较,如果发现完全相同,就没有必要进行第二部分运算了,选择器直接把之前第二部分的运算结果返回就可以了
     */
    const getFilter = (state) => state.filter;
    const getTodos = (state) => state.todos;
    
    // 第一个参数是一个函数数组,每个元素代表了选择器步骤一需要做的映射计算,这里我们提供了两个函数getFilte和getTodos
    export const selectVisibleTodos = createSelector(
      [getFilter, getTodos],
      (filter, todos) => {
        switch (filter) {
          case FilterTypes.ALL:
            return todos;
          case FilterTypes.COMPLETED:
            return todos.filter(item => item.completed);
          case FilterTypes.UNCOMPLETED:
            return todos.filter(item => !item.completed);
          default:
            throw new Error('unsupported filter');
        }
      }
    );
    
    // todoList.js
    import React, {PropTypes} from 'react';
    import {connect} from 'react-redux';
    import TodoItem from './todoItem.js';
    import {selectVisibleTodos} from '../selector.js';
    
    const TodoList = ({todos, onClickTodo}) => {
      return (
        <ul className="todo-list">
        {
          todos.map((item) => (
            <TodoItem
              key={item.id}
              id={item.id}
              text={item.text}
              completed={item.completed}
            />
            ))
        }
        </ul>
      );
    };
    
    TodoList.propTypes = {
      todos: PropTypes.array.isRequired
    };
    
    const mapStateToProps = (state) => {
      return {
        todos: selectVisibleTodos(state)
      };
    }
    
    export default connect(mapStateToProps)(TodoList);
    

范式化状态树

  • Redux Store 的状态树应该设计的尽量扁平且范式化
  • 范式化:遵照关系型数据库的设计原则,减少冗余数据。范式化的数据结构设计就是要让一份数据只存储一份,数据冗余造成的后果就是难以保证数据一致性
  • 反范式化:
    反范式化数据结构的特点就是读取容易,修改比较麻烦。在这里插入图片描述
  • 范式化:
    在这里插入图片描述
    用一个typeId代表类型,然后在Redux Store上和todos平级的根节点位置创建一个types字段,内容是一个数组,每个数组元素代表一个类型,一个种类的数据是类似下面的对象:
    在这里插入图片描述
    当TodoItem组件要渲染内容时,从Redux Store状态树的todos字段下获取的数据是不够的,因为只有typeId。为了获得对应的种类名称和颜色,需要做一个类似关系型数据库的join操作,到状态树的types字段下去寻找对应typeId的种类数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值