這篇文章帶大家聊聊Redux Hooks的使用細節,希望對大家有幫助!
在先前的redux開發中,為了讓元件和redux結合起來,我們使用了react-redux函式庫中的connect:
但是這種方式必須使用高階函數結合傳回的高階元件;
且必須寫:mapStateToProps和mapDispatchToProps映射的函數, 具體使用方式在前面文章有講解;【相關推薦:Redis影片教學、程式設計影片 】
在Redux7.1開始,提供了Hook的方式,在函數元件中再也不需要編寫connect以及對應的映射函數了
useSelector
的作用是將state對應到元件中:
參數一: 要求傳入一個回呼函數, 會將state傳遞到該回呼函數中; 回呼函數的傳回值要求是一個物件, 在物件編寫要使用的資料, 我們可以直接對這個傳回的物件進行解構, 拿到我們要使用state中的資料
const { counter } = useSelector((state) => { return { counter: state.counter.counter } })登入後複製參數二: 可以進行比較來決定是否要元件重新渲染;
useSelector預設會比較我們傳回的兩個物件是否相等;
如何可以比較呢?
- 在useSelector的第二個參數中, 傳入react-redux庫中的
shallowEqual
函數就可以進行比較import { shallowEqual } from 'react-redux' const { counter } = useSelector((state) => ({ counter: state.counter.counter }), shallowEqual)登入後複製也就是我們必須回傳兩個完全相等的物件才可以不引起重新渲染;
useDispatch
非常簡單,就是呼叫useDispatch這個Hook, 就可以直接取得到dispatch函數,之後在元件中直接使用即可;
const dispatch = useDispatch()
我們也可以透過useStore來取得目前的store物件(了解即可, 不建議直接操作store物件);
我們來使用Redux的Hooks在App元件實作一個計數器, 在App的子元件中實作一個修改message的案例:
首先我們先建立一個簡單的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函式庫需要匯入Provider對App元件進行包裹
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實作來取得store中的資料和修改store中資料的動作
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中的数据 const { message } = useSelector((state) => ({ message: state.counter.message })) // useDispatch获取到dispatch函数 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中的数据 const { counter } = useSelector((state) => ({ counter: state.counter.counter })) // useDispatch获取到dispatch函数 const dispatch = useDispatch() function changeNumber(num) { dispatch(changeNumberAction(num)) } return ( <div> <h2>当前计数: {counter}</h2> <button onClick={() => changeNumber(1)}>+1</button> <button onClick={() => changeNumber(-1)}>-1</button> <Home/> </div> ) }) export default App
現在我們已經在元件中使用並且修改了了store中的資料, 但是現在還有一個小問題(效能最佳化)
#當App元件中修改了counter, App元件會重新渲染這個是沒問題的; 但是Home組件中使用的是message, 並沒有使用counter, 卻也會重新渲染; 同樣的在Home子組件中修改了message, 根組件App也會重新渲染; 這是因為在默認情況下useSelector是監聽的整個state, 當state發生改變就會導致組件重新渲染
要解決這個問題就需要使用useSelector的第二個參數來控制是否需要重新渲染, 我們只需要在useSelector函數中傳入react-redux庫中的
shallowEqual
函數即可, 它內部會自動進行一個淺層比較, 當使用的state中的資料確實發生變化的時候才會重新渲染
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中的数据 const { counter } = useSelector((state) => ({ counter: state.counter.counter }), shallowEqual) // useDispatch获取到dispatch函数 const dispatch = useDispatch() function changeNumber(num) { dispatch(changeNumberAction(num)) } return ( <div> <h2>当前计数: {counter}</h2> <button onClick={() => changeNumber(1)}>+1</button> <button onClick={() => changeNumber(-1)}>-1</button> <Home/> </div> ) }) export default App
更多程式相關知識,請造訪:程式設計教學! !
以上是一文詳解Redux Hooks的使用細節的詳細內容。更多資訊請關注PHP中文網其他相關文章!