react 之 useCallback

首先了解之前大家一定要看一次文档

官方地址: 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值