简介: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
}
思考:现在的诊疗圈的是否没有实现该种情况?并且没有解决