1

简介:redux的优化方案就是reselect,类似于vue的getter

解决了什么:

我们从store中state获取的数据,需要经过计算换成了组件可使用的数据,每次使用,每次都要重新计算,如果 state tree 非常大,或者计算量非常大,每次更新都重新计算可能会带来性能问题,reselect就相当于一个备忘录,内部会做些缓存的计算,且只有与该reselect相关的state变化时,reselect才会重新计算

特点:

可记忆的(Memoized)
可组合的 selector 函数

api:

参数:
input-selectors 数组
转换函数

机制:
state tree改变 -> input-selector变化 -> selector调用转换函数
state tree不变 -> input-selector不变 -> 直接返回前一次计算的数据,不调用selector

import { createSelector } from 'reselect'

const shopItemsSelector = state, => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent

const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

const taxSelector = createSelector(
  subtotalSelector,
  taxPercentSelector,
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
)

连接 Selector 和 Redux Store

    const mapStateToProps = (state) => {
      return {
        todos: getVisibleTodos(state)
      }
    }
    
    // 诊疗圈
    // selectList: 通过immutable转为普通js对象
    const mapStateToProps = createSelector(
      selectList,
      selectShowMore,
      selectLoading,
      ($collectList, showMore, loading) => ({
        collectList: $collectList.toJS(),
        showMore,
        loading,
      }),
    )

selectors 中访问 React Props

props 可以通过 mapStateToProps 传递给 getVisibleTodos:

const getTodos = (state, props) => state.todoLists[props.listId].todos

const mapStateToProps = (state, props) => {
  return {
    todos: getVisibleTodos(state, props)
  }
}

多组件的共享 Selector

每个组件的实例需要有拷贝 selector 的私有版本
1.我们创建一个 makeGetVisibleTodos 的函数,在每个调用的时候返回一个 getVisibleTodos selector 的新拷贝
2.我们还需要一种每个容器访问自己私有 selector 的方式

如果 connect 的 mapStateToProps 返回的不是一个对象而是一个函数,他将被用做为每个容器的实例创建一个单独的 mapStateToProps 函数

eg:

import React from 'react'
import Footer from './Footer'
import AddTodo from '../containers/AddTodo'
import VisibleTodoList from '../containers/VisibleTodoList'

const App = () => (
  <div>
    <VisibleTodoList listId="1" />
    <VisibleTodoList listId="2" />
    <VisibleTodoList listId="3" />
  </div>
)

用 createSelector 创建的 selector 只有在参数集与之前的参数集相同时才会返回缓存的值。
如果我们交替的渲染 VisibleTodoList listId="1" /> 和 VisibleTodoList listId="2" />,共享的 selector 将交替的接收 listId: 1 和 listId: 2。
这会导致每次调用时传入的参数不同,因此 selector 将始终重新计算而不是返回缓存的值。


const makeGetVisibleTodos = () => {
  return createSelector(
    [ getVisibilityFilter, getTodos ],
    (visibilityFilter, todos) => {
      switch (visibilityFilter) {
        case 'SHOW_COMPLETED':
          return todos.filter(todo => todo.completed)
        case 'SHOW_ACTIVE':
          return todos.filter(todo => !todo.completed)
        default:
          return todos
      }
    }
  )
}

const makeMapStateToProps = () => {
  const getVisibleTodos = makeGetVisibleTodos()
  const mapStateToProps = (state, props) => {
    return {
      todos: getVisibleTodos(state, props)
    }
  }
  return mapStateToProps
}

思考:现在的诊疗圈的是否没有实现该种情况?并且没有解决


Rainie
441 声望36 粉丝

全栈攻城狮