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