React中Redux Hooks的使用詳解
Redux Hooks
Redux中Hooks介紹
在之前的redux開發(fā)中,為了讓組件和redux結(jié)合起來,我們使用了react-redux庫中的connect:
但是這種方式必須使用高階函數(shù)結(jié)合返回的高階組件;
并且必須編寫:mapStateToProps和 mapDispatchToProps映射的函數(shù), 具體使用方式在前面文章有講解;
在Redux7.1開始,提供了Hook的方式,在函數(shù)組件中再也不需要編寫connect以及對應(yīng)的映射函數(shù)了
useSelector
的作用是將state映射到組件中:
參數(shù)一: 要求傳入一個回調(diào)函數(shù), 會將state傳遞到該回調(diào)函數(shù)中; 回調(diào)函數(shù)的返回值要求是一個對象, 在對象編寫要使用的數(shù)據(jù), 我們可以直接對這個返回的對象進(jìn)行解構(gòu), 拿到我們要使用state中的數(shù)據(jù)
const { counter } = useSelector((state) => { return { counter: state.counter.counter } })
參數(shù)二: 可以進(jìn)行比較來決定是否組件重新渲染;
useSelector默認(rèn)會比較我們返回的兩個對象是否相等;
如何可以比較呢?
在useSelector的第二個參數(shù)中, 傳入react-redux庫中的shallowEqual
函數(shù)就可以進(jìn)行比較
import { shallowEqual } from 'react-redux' const { counter } = useSelector((state) => ({ counter: state.counter.counter }), shallowEqual)
也就是我們必須返回兩個完全相等的對象才可以不引起重新渲染;
useDispatch
非常簡單,就是調(diào)用useDispatch這個Hook, 就可以直接獲取到dispatch函數(shù),之后在組件中直接使用即可;
const dispatch = useDispatch()
我們還可以通過useStore來獲取當(dāng)前的store對象(了解即可, 不建議直接操作store對象);
Redux中Hooks使用
我們來使用Redux的Hooks在App組件實現(xiàn)一個計數(shù)器, 在App的子組件中實現(xiàn)一個修改message的案例:
首先我們先創(chuàng)建一個簡單的store
// store/modules/counter.js import { createSlice } from "@reduxjs/toolkit"; const counterSlice = createSlice({ name: "counter", initialState: { counter: 10, message: "Hello World" }, reducers: { changeNumberAction(state, { payload }) { state.counter = state.counter + payload }, changeMessageAction(state, {payload }) { state.message = payload } } }) export const { changeNumberAction, changeMessageAction } = counterSlice.actions export default counterSlice.reducer
// store/index.js import { configureStore } from "@reduxjs/toolkit"; import counterSlice from "./modules/counter" const store = configureStore({ reducer: { counter: counterSlice } }) export default store
要使用react-redux庫需要導(dǎo)入Provider對App組件進(jìn)行包裹
import React from "react" import ReactDOM from "react-dom/client" import { Provider } from "react-redux" import App from "./12_Redux中的Hooks/App" import store from "./12_Redux中的Hooks/store" const root = ReactDOM.createRoot(document.querySelector("#root")) root.render( <Provider store={store}> <App/> </Provider> )
在組件時使用useSelector和useDispatch實現(xiàn)獲取store中的數(shù)據(jù)和修改store中數(shù)據(jù)的操作
import React, { memo } from 'react' import { useDispatch, useSelector } from 'react-redux' import { changeMessageAction, changeNumberAction } from './store/modules/counter' // 子組件Home const Home = memo(() => { console.log("Home組件重新渲染") // 通過useSelector獲取到store中的數(shù)據(jù) const { message } = useSelector((state) => ({ message: state.counter.message })) // useDispatch獲取到dispatch函數(shù) const dispatch = useDispatch() function changeMessage() { dispatch(changeMessageAction("Hello ChenYq")) } return ( <div> <h2>{message}</h2> <button onClick={changeMessage}>修改message</button> </div> ) }) // 根組件App const App = memo(() => { console.log("App組件重新渲染") // 通過useSelector獲取到store中的數(shù)據(jù) const { counter } = useSelector((state) => ({ counter: state.counter.counter })) // useDispatch獲取到dispatch函數(shù) const dispatch = useDispatch() function changeNumber(num) { dispatch(changeNumberAction(num)) } return ( <div> <h2>當(dāng)前計數(shù): {counter}</h2> <button onClick={() => changeNumber(1)}>+1</button> <button onClick={() => changeNumber(-1)}>-1</button> <Home/> </div> ) }) export default App
現(xiàn)在我們已經(jīng)在組件中使用并且修改了了store中的數(shù)據(jù), 但是現(xiàn)在還有一個小問題(性能優(yōu)化)
當(dāng)App組件中修改了counter時, App組件會重新渲染這個是沒問題的; 但是Home組件中使用的是message, 并沒有使用counter, 卻也會重新渲染; 同樣的在Home子組件中修改了message, 根組件App也會重新渲染; 這是因為在默認(rèn)情況下useSelector是監(jiān)聽的整個state, 當(dāng)state發(fā)生改變就會導(dǎo)致組件重新渲染
要解決這個問題就需要使用useSelector的第二個參數(shù)來控制是否需要重新渲染, 我們只需要在useSelector函數(shù)中傳入react-redux庫中的
shallowEqual
函數(shù)即可, 它內(nèi)部會自動進(jìn)行一個淺層比較, 當(dāng)使用的state中的數(shù)據(jù)確實發(fā)生變化的時候才會重新渲染
import React, { memo } from 'react' import { useDispatch, useSelector, shallowEqual } from 'react-redux' import { changeMessageAction, changeNumberAction } from './store/modules/counter' // 子組件Home const Home = memo(() => { console.log("Home組件重新渲染") const { message } = useSelector((state) => ({ message: state.counter.message }), shallowEqual) const dispatch = useDispatch() function changeMessage() { dispatch(changeMessageAction("Hello ChenYq")) } return ( <div> <h2>{message}</h2> <button onClick={changeMessage}>修改message</button> </div> ) }) // 根組件App const App = memo(() => { console.log("App組件重新渲染") // 通過useSelector獲取到store中的數(shù)據(jù) const { counter } = useSelector((state) => ({ counter: state.counter.counter }), shallowEqual) // useDispatch獲取到dispatch函數(shù) const dispatch = useDispatch() function changeNumber(num) { dispatch(changeNumberAction(num)) } return ( <div> <h2>當(dāng)前計數(shù): {counter}</h2> <button onClick={() => changeNumber(1)}>+1</button> <button onClick={() => changeNumber(-1)}>-1</button> <Home/> </div> ) }) export default App
到此這篇關(guān)于React - Redux Hooks的使用細(xì)節(jié)詳解的文章就介紹到這了,更多相關(guān)React Redux Hooks使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react函數(shù)組件useState異步,數(shù)據(jù)不能及時獲取到的問題
這篇文章主要介紹了react函數(shù)組件useState異步,數(shù)據(jù)不能及時獲取到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08react router4+redux實現(xiàn)路由權(quán)限控制的方法
本篇文章主要介紹了react router4+redux實現(xiàn)路由權(quán)限控制的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05解決react中l(wèi)abel標(biāo)簽for報錯問題
這篇文章主要介紹了react中l(wèi)abel標(biāo)簽for報錯問題,解決辦法就是react中l(wèi)abel標(biāo)簽沒有for屬性,用htmlFor代替for屬性,感興趣的朋友跟隨小編一起看看吧2022-02-02React?Hooks--useEffect代替常用生命周期函數(shù)方式
這篇文章主要介紹了React?Hooks--useEffect代替常用生命周期函數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09