前言
隨着react hooks
越來越火,react-redux
也緊隨其後發佈了7.1
(https://react-redux.js.org/api/hooks#using-hooks-in-a-react-redux-app)版本
首先是幾個API
- useSelector()
const result : any = useSelector(selector : Function, equalityFn? : Function)
主要作用:
從redux
的store
對象中提取數據(state
)。
注意:選擇器函數應該是純函數,因爲它可能在任意時間點多次執行。
import React from 'react'
import { useSelector } from 'react-redux'
export const CounterComponent = () => {
const counter = useSelector(state => state.counter)
return <div>{counter}</div>
}
- useDispatch()
const dispatch = useDispatch()
返回Redux
store
中對dispatch
函數的引用。你可以根據需要使用它。
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>
)
}
將回調使用dispatch
傳遞給子組件時,建議使用來進行回調useCallback
,因爲否則,由於更改了引用,子組件可能會不必要地呈現。
import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
const incrementCounter = useCallback(
() => dispatch({ type: 'increment-counter' }),
[dispatch]
)
return (
<div>
<span>{value}</span>
<MyIncrementButton onIncrement={incrementCounter} />
</div>
)
}
export const MyIncrementButton = React.memo(({ onIncrement }) => (
<button onClick={onIncrement}>Increment counter</button>
))
- useStore()
const store = useStore()
這個Hook
返回redux
<Provider>
組件的store
對象的引用。
這個鉤子應該不長被使用。useSelector
應該作爲你的首選。但是,有時候也很有用。來看個例子:
import React from 'react'
import { useStore } from 'react-redux'
export const CounterComponent = ({ value }) => {
const store = useStore()
// 僅僅是個例子! 不要在你的應用中這樣做.
// 如果store中的state改變,這個將不會自動更新
return <div>{store.getState()}</div>
}
dva中如何使用
dva
在[email protected][1]
的beta版本發佈了這幾個API
,如果我們想使用他,首先安裝指定版本的
yarn add [email protected]
// or
npm install [email protected]
並且這樣使用
import { useSelector, useDispatch } from 'dva';
如果不想升級dva
版本的話我們需要安裝
yarn add [email protected]
並且這樣使用
import { useSelector, useDispatch } from 'react-redux';
首先先看原始dva
的寫法
先定義一個user model
// 1.user.js ==>model
export default {
namespace: 'user',
state: {
userInfo:null,
},
effects: {
*fetchUser({paylaod},{call,put}){
const res = yield(api,payload)
yield put({
type: 'save',
payload: {
userInfo:res
},
});
}
},
reducers:{
save(state, { payload }) {
return {
...state,
...payload,
};
},
}
}
然後在頁面中使用
import {connect} from 'dva'
const Home = props=>{
// 獲取數據
const {user,loading,dispatch} = props
// 發起請求
useEffect(()=>{
dispatch({
type:'user/fetchUser',payload:{}
})
},[])
// 渲染頁面
if(loading) return <div>loading...</div>
return (
<div>{user.name}<div>
)
}
export default connect(({loading,user})=>({
loading:loading.effects['user/fetchUser'],
user:user.userInfo
}))(Home)
connect
這個高階組件裏定義了太多東西,這種寫法太噁心了。
如果太多數據從props
獲取的話,connect
裏堆了太多代碼
下面我們使用useDispatch
useSelector
優化上面的代碼
import {useDispatch,useSelector} from 'dva'
const Home = props=>{
const dispatch = useDispatch()
const loadingEffect = useSelector(state =>state.loading);
const loading = loadingEffect.effects['user/fetchUser'];
const user = useSelector(state=>state.user.userInfo)
// 發起請求
useEffect(()=>{
dispatch({
type:'user/fetchUser',payload:{}
})
},[])
// 渲染頁面
if(loading) return <div>loading...</div>
return (
<div>{user.name}<div>
)
}
export default Home
使用useSelector
useDispatch
替代connect