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 函数```jsximport 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 changesreturn <div>{store.getState()}</div>}
