React-redux 7.1发版啦。
因为在新的项目中用到了hooks,但是用的时候react-redux还处于alpha.x
版本的状态。用不了最新的API,感觉不是很美妙。好在,这两天发布了7.1版本。
现在来看看怎么用这个新的API。
useSelector()
const result : any = useSelector(selector : Function, equalityFn? : Function)
这个是干啥的呢?就是从redux的store对象中提取数据(state)。
注意: 因为这个可能在任何时候执行多次,所以你要保持这个selector是一个纯函数。
这个selector方法类似于之前的connect的mapStateToProps参数的概念。并且useSelector
会订阅store, 当action被dispatched的时候,会运行selector。
当然,仅仅是概念和mapStateToProps相似,但是肯定有不同的地方,看看selector和mapStateToProps的一些差异:
- selector会返回任何值作为结果,并不仅仅是对象了。然后这个selector返回的结果,就会作为
useSelector
的返回结果。
- 当action被dispatched的时候,
useSelector()
将对前一个selector结果值和当前结果值进行浅比较。如果不同,那么就会被re-render。 反之亦然。
- selector不会接收ownProps参数,但是,可以通过闭包(下面有示例)或使用柯里化selector来使用props。
- 使用记忆(memoizing) selector时必须格外小心(下面有示例)。
-
useSelector()
默认使用===
(严格相等)进行相等性检查,而不是浅相等(==
)。
你可能在一个组件内调用useSelector
多次,但是对useSelector()
的每个调用都会创建redux store的单个订阅。由于react-reduxv7版本使用的react的批量(batching)更新行为,造成同个组件中,多次useSelector返回的值只会re-render一次。
相等比较和更新
当函数组件渲染时,会调用提供的selector函数,并且从useSelector
返回其结果。(如果selector运行且没有更改,则会返回缓存的结果)。
上面有说到,只当对比结果不同的时候会被re-render。从v7.1.0-alpha.5开始,默认比较是严格比较(===
)。这点于connect的时候不同,connect使用的是浅比较。这对如何使用useSelector()
有几个影响。
使用mapState
,所有单个属性都在组合对象中返回。返回的对象是否是新的引用并不重要 - connect()
只比较各个字段。使用useSelector
就不行了,默认情况下是,如果每次返回一个新对象将始终进行强制re-render。如果要从store中获取多个值,那你可以这样做:
-
useSelector()
调用多次,每次返回一个字段值。
-
使用Reselect或类似的库创建一个记忆化(memoized) selector,它在一个对象中返回多个值,但只在其中一个值发生更改时才返回一个新对象。
-
使用react-redux 提供的shallowEqual
函数作为useSelector
的equalityFn
参数。
就像下面这样:
import {
shallowEqual, useSelector } from 'react-redux'
// later
const selectedData = useSelector(selectorReturningObject, shallowEqual)
useSelector 例子
上面做了一些基本的阐述,下面该用一些例子来加深理解。
基本用法
import React from 'react'
import {
useSelector } from 'react-redux'
export const CounterComponent = () => {
const counter = useSelector(state => state.counter)
return <div>{
counter}</div>
}
通过闭包使用props来确定要提取的内容:
import React from 'react'
import {
useSelector } from 'react-redux'
export const TodoListItem = props => {
const todo = useSelector(state => state.todos[props.id])
return