hooks 首次添加于版本 v7.1.0
React Redux 现在提供了一组 Hook,用以代替
connect()
高阶组件,这些API
允许订阅Redux state
和dispatch actions
,而不必将组建包装在connect()
中
使用前提:和使用 connect()
一样,你首先应该将整个应用包裹在 <Provider>
中,使得 store 暴露在整个组件树中
const store = createStore(rootReducer)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
1. useSelector
使用选择器功能从 Redux store
状态中提取数据,类似于 connect
中的 mapStateToProps
参数。将以整个 Redux store
状态作为唯一参数来调用选择器
const result: any = useSelector(selector: Function, equalityFn?: Function)
⚠️:选择器函数应是一个纯函数
useSelector()
同样会订阅 Redux 的 store,并且在你每分发 dispatch 一个 action 时,都会被执行一次selector
:接收 store 的 state 整个值,它的返回值将作为useSeletor()
的返回值- 当 dispatch 了一个 action 时,
useSelector
会将上一次调用 selector 函数的执行结果与当前调用的结果进行引用(===)
比较,如果不一样,组件会被强制重新渲染。如果一样,就不会被重新渲染。用法举例
```jsx import React from ‘react’ import { useSelector } from ‘react-redux’
export const CounterComponent = () => { const counter = useSelector(state => state.counter) return
{counter}
}
在使用 `useSelector` 时使用单行箭头函数,会导致在每次渲染期间都会创建一个新的 selector 函数。可以看出,这样的 selector 函数并没有维持任何的内部状态。
解决方式:使用 reselect 库,实现记忆化的 selector 函数
```jsx
import React from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'
// 返回 isDone 的 todo 的长度
const selectNumOfDoneTodos = createSelector(
state => state.todos,
todos => todos.filter(todo => todo.isDone).length
)
export const DoneTodosCounter = () => {
const NumOfDoneTodos = useSelector(selectNumOfDoneTodos)
return <div>{NumOfDoneTodos}</div>
}
export const App = () => {
return (
<>
<span>Number of done todos:</span>
<DoneTodosCounter />
</>
)
}
2. useDispatch
这个 hook 返回 Redux store 的 分发(dispatch) 函数的引用,用来 dispatch 某些需要的 action
const dispatch = useDispatch()
用法举例
import React from 'react'
import { useDispatch } from 'react-redux'
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
return (
<div>
<span>{value}</span>
<button onClick={() => dispatch({ type: 'increment-counter' })}>
Increment counter
</button>
</div>
)
}
3. useStore
这个 hook 返回传递给 组件的 Redux store 的引用
这个 hook 也许不应该被经常使用。 你应该将 useSelector() 作为你的首选。 但是,在一些不常见的场景下,你需要访问 store,这个还是有用的,比如替换 store 的 reducers
用法举例
import React from 'react'
import { useStore } from 'react-redux'
export const CounterComponent = ({ value }) => {
const store = useStore()
// EXAMPLE ONLY! Do not do this in a real app.
// The component will not automatically update if the store state changes
return <div>{store.getState()}</div>
}