React 第十六节 useCallback 使用详解注意事项

发布于:2024-12-18 ⋅ 阅读:(200) ⋅ 点赞:(0)

useCallback 概述

1、useCallback 是在React 中多次渲染缓存函数的 Hook,返回一个函数的 memoized的值;
2、如果多次传入的依赖项不变,那么多次定义的时候,返回的值是相同的,防止频繁触发更新;
3、多应用在 父组件为函数式组件,子组件也为函数式组件,并且子组件被 React.memo() 包裹着;
4、主要用于性能优化,即使不适用useCallback,代码也要能正常运行;

useCallback 基本用法

写法

let memoizedCallback = useCallback(fn, dependencies)

第一个参数fn 是想要缓存的函数,可以接收任何参数并返回任何值;React 中会在初始化时候调用,而不是渲染时候调用;
当执行下一次渲染时候,如何出入的依赖值 dependencies 相同,则会返回相同的函数 memoizedCallback
相反 若依赖值 dependencies 不同,则会返回新的函数 memoizedCallback,但是 React 不会主动去调用 memoizedCallback函数,需要开发者自己决定什么时候执行调用函数;

第二个参数
dependencies:是否要更新 fn 的所有响应式值的一个列表,可以传入空数组:[]
响应式值包括 props、state,和所有在你组件内部直接声明的变量和函数。

useCallback 示例

1、为什么要使用 useCallback

当我们传入相同值的时候,不管是对象类型,还是基本类型,都不希望子组件进行更新渲染;
在不需要大量渲染的时候,性能还可以,但是当数据量大的时候,若相同的数据也触发子组件渲染,则会出现性能问题;

2、在不使用 useCallback() 的时候

每次触发 handleAdd 事件时候,都会渲染子组件 ChildA

//  父组件
import { useCallback,  useState} from 'react'
import ChildA from './childA'
export default function MyCallBack() {

   const [useInfo, setUseInfo] = useState({
       name: 'Andy',
       age: 18
   })
   const myCallback = () => {
       console.log('==useCallback==')
       return useInfo.name
   }

   const handleAdd = () => {
       setUseInfo({
           name: 'Andy',
           age: 18
       })
   }
 return (
   <div>
     <h3>This is a MyCallBack demo .---{count}</h3>
       <button onClick={handleAdd}>add</button>
        <hr />
       <ChildA  onAddCount={myCallback} ></ChildA>
   </div>
 )
}

// 子组件
import React, { memo } from 'react'

const  ChildA = memo(({onAddCount}) => {
    console.log('==ChildA 组件更新了=', count)
    return (
        <div>
        <h3>This is a ChildA demo .</h3>
            <button onClick={onAddCount}>子组件</button>
            <hr />
        </div>
    )
})

当我们点击 add 按钮时候,发现页面打印 “==ChildA 组件更新了=”,说明传入相同的数据时候,会触发子组件渲染;如图所示

在这里插入图片描述

3、使用 useCallback 时候

import { useCallback,useState} from 'react'
import ChildA from './childA'
export default function MyCallBack() {
  console.log('===父组件callback==')
    const [count, setCount] = useState(0)
    const [useInfo, setUseInfo] = useState({
        name: 'Andy',
        age: 18
    })
    const myCallback = useCallback(() => {
        console.log('==useCallback==')
        return useInfo.name
    }, [useInfo.name])
    const handleAdd = () => {
        setUseInfo({
            name: 'Andy',
            age: 18
        })
    }
  return (
    <div>
      <h3>This is a MyCallBack demo .---{count}</h3>
        <button onClick={handleAdd}>add</button>
         <hr />
        <ChildA  onAddCount={myCallback} ></ChildA>
    </div>
  )
}

// 子组件
import { memo } from 'react'
// eslint-disable-next-line react/display-name
const  ChildA = memo(({useInfo, count, onAddCount}) => {
    console.log('==ChildA 组件更新了=', count)
    const handleChangeName = () =>{
            setName('Tom')
       }
    return (
        <div>
        <h3>This is a ChildA demo .</h3>
            <h4>{count}</h4>
            <h4>姓名:{useInfo?.name || '--'}</h4>
            <h4>年龄:{useInfo?.age || '--'}</h4>
            <button onClick={onAddCount}>子组件</button>
            <hr />
        </div>
    )
})
export default  ChildA 

在点击 add 按钮 更新相同数据时候,只有父组件渲染子组件不会再渲染;如图:在这里插入图片描述

总结

若要实现 传入相同数据时候,只更新当前组件,而子组件不进行渲染,需使用 useCallback() 和 memo 来处理


网站公告

今日签到

点亮在社区的每一天
去签到