首先了解之前大家一定要看一次文档
官方地址: Hook API 索引 – Reacthttps://zh-hans.reactjs.org/docs/hooks-reference.html#usecallback
把内联回调函数及依赖项数组作为参数传入 useCallback
,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate
)的子组件时,它将非常有用。
我们可以看到官方这句话,它的具体含义我举例子说明一下
首先,创建一个 Test.js 组件,它接收一个 value props,别忘了它子组件需要 React.memo 包裹
import React from "react"
import { useDispatch } from "react-redux"
import { increment } from "../features/counterSlice"
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
const incrementCounter = () => dispatch(increment())
return (
<div>
<span>{value}</span>
<MyIncrementButton onIncrement={incrementCounter} />
</div>
)
}
export const MyIncrementButton = React.memo(({ onIncrement }) => {
console.log('render')
return <button onClick={onIncrement}>Increment counter</button>
})
我们的 counterSlice.js 代码如下
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: (state) => {
state.value += 1;
}
}
});
export const { increment } = counterSlice.actions;
export default counterSlice.reducer;
记得别忘了在 store.reducer 中注入
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
然后我们在 App.js 中使用该组件
import React from 'react';
import { CounterComponent } from './components/Test';
import { useSelector } from 'react-redux'
function App() {
const count = useSelector(state => state.counter.value)
return (
<div className="App">
<CounterComponent value={count} />
</div>
);
}
export default App;
启动项目后,我们点击 increment counter 按钮,可以看到控制台一直在打印 render
这并不是我们想要的,因为我们改变了 counter 之后,子组件 MyIncrementButton 并没有任何其他修改,所以不应该重新渲染它
所以我们改变一下 CounterComponent 组件
import React, { useCallback } from "react"
import { useDispatch } from "react-redux"
import { increment } from "../features/counter/counterSlice"
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
const incrementCounter = useCallback(() => dispatch(increment()), [dispatch])
return (
<div>
<span>{value}</span>
<MyIncrementButton onIncrement={incrementCounter} />
</div>
)
}
export const MyIncrementButton = React.memo(({ onIncrement }) => {
console.log('render')
return <button onClick={onIncrement}>Increment counter</button>
})
给它加入 useCallback
这个时候我们再点击 increment counter 按钮的时候,会发现控制台并没有再持续打印 render 了
这是因为 useCallback 第二个参数,表示 dispatch 并没有改变,所以该钩子返回的值就不会改变,继而不会渲染子组件,useCallback 的使用对页面的加载速度有很大的优化,大家应该经常对该应用场景进行使用
同样的优化还有 useSelector,请参考 CSDNhttps://mp.csdn.net/mp_blog/creation/editor/120859456