您的位置:首页 > 游戏 > 游戏 > 小微平台_网店美工培训_网站优化就是搜索引擎优化_营销自动化工具

小微平台_网店美工培训_网站优化就是搜索引擎优化_营销自动化工具

2024/12/26 13:38:53 来源:https://blog.csdn.net/weixin_43285360/article/details/142353421  浏览:    关键词:小微平台_网店美工培训_网站优化就是搜索引擎优化_营销自动化工具
小微平台_网店美工培训_网站优化就是搜索引擎优化_营销自动化工具

概述

useCallback缓存的是一个函数,主要用于性能优化!!!

基本用法

如何进行性能的优化呢?

  • useCallback会返回一个函数的 memoized(记忆的) 值;
  • 在依赖不变的情况下,多次定义的时候,返回的值是相同的;

语法:

const memoizedCallback = useCallback(() => {doSomething(a, b);},[a, b],
);
  • 通常使用useCallback的目的是不希望子组件进行多次渲染,并不是为了函数进行缓存;
  • 在使用 React.memo 时,对于对象类型的 props,只会比较引用(浅对比)。
  • 但是,因为组件每次更新都会创建新的 props 值,比如,新的对象、事件处理程序等(函数组件的特性)。
  • 这就导致:React.memo 在处理对象类型的 props 时,会失效(每次的 props 都是新对象)。
  • 但是,我们还是想让 React.memo 在处理对象类型的 props 时,也有效。
  • 为了让 React.memo 处理对象类型的 props 有效,只要在组件更新期间保持对象类型引用相等即可

这时候,就要用到以下两个 Hooks:

  • useCallback Hook:记住函数的引用,在组件每次更新时返回相同引用的函数。
  • useMemo Hook:记住任意数据(数值、对象、函数等),在组件每次更新时返回相同引用的数据【功能之一】

示例:

import {useCallback, useState} from "react";export default function UseCallback() {let [firstName, setFirstName] = useState('张');let [lastName, setLastName] = useState('三');let getFullName = useCallback(() => {return firstName + lastName}, [firstName, lastName])return (<div>姓名:{getFullName()}</div>)
}

缓存了一个函数,可以在组件中使用!!!

演示示例

使用场景:在使用 React.memo 时,为了组件每次更新时都能获取到相同引用的函数,就要用到 useCallback Hook

注意:需要配合 React.memo 高阶函数一起使用

作用:记忆传入的回调函数,这个被记住的回调函数会一直生效,直到依赖项发生改变

解释:

  • 第一个参数:必选,需要被记忆的回调函数。
  • 第二个参数:必选,依赖项数组,用于指定回调函数中依赖(用到)的数据(类似于 useEffect 的第二个参数)。
  • 即使没有依赖,也得传入空数组([]),此时,useCallback 记住的回调函数就会一直生效。
  • 返回值:useCallback 记住的回调函数。
  • useCallback 记住的回调函数会一直生效(或者说会一直返回同一个回调函数),直到依赖项发生改变。
import React, { memo, useState, useCallback, useRef } from 'react'const App = memo(() => {const [count, setCount] = useState(0)const [money, setMoney] = useState(1000)// 初始写法const help = useCallback(() => {setCount(count - 1)}, [count])// 优化写法:useRef--在组件多次渲染时,返回的是同一个值// 这种写法容易陷入闭包陷阱const help = useCallback(() => {setCount(count - 1)}, [])// 推荐优化写法:const countRef = useRef();countRef.current = count;const help = useCallback(() => {setCount(countRef.current - 1)}, [])return (<div><h1>计数器</h1><div>豆豆被打了{count}次</div><div>金钱:{money}</div><button onClick={() => setCount(count + 1)}>打豆豆</button><button onClick={() => setMoney(money + 100)}>加钱</button><hr />{count < 5 ? <DouDou count={count} help={help}></DouDou> : '豆豆被打死了'}</div>)
})export default App

Doudou.jsx

// 子组件
const DouDou = memo(({ count, help }) => {console.log('豆豆组件渲染')return (<div><h3>我是豆豆组件{count}</h3><button onClick={help}>续命</button></div>)
})
export default Doudou

总结:

要配合  memo 不然可能反而会降低性能

  1. 当需要将一个函数传递给子组件,最好使用 useCallback 进行优化,将优化之后的函数,传递给子组件
  2. 当需要将一个函数传递给子组件时,最好使用useCallback进行优化,将优化之后的函数传递给子组件

尽量不要使用 useCallback

我建议在项目中尽量不要用 useCallback,大部分场景下,不仅没有提升性能,反而让代码可读性变的很差。

useCallback 大部分场景没有提升性能

useCallback 可以记住函数,避免函数重复生成,这样函数在传递给子组件时,可以避免子组件重复渲染,提高性能。

基于以上认知,很多人(包括我自己)在写代码时,只要是个函数,都加个 useCallback,是你么?反正我以前是。

但我们要注意,提高性能还必须有另外一个条件,子组件必须使用了 shouldComponentUpdate 或者 来忽略同样的参数重复渲染。

假如 ExpensiveComponent 组件只是一个普通组件,是没有任何用的。比如下面这样:

必须通过 React.memo 包裹 ExpensiveComponent ,才会避免参数不变的情况下的重复渲染,提高性能。

所以,useCallback 是要和 shouldComponentUpdate/React.memo 配套使用的,你用对了吗?当然,我建议一般项目中不用考虑性能优化的问题,也就是不要使用 useCallback 了,除非有个别非常复杂的组件,单独使用即可。

useCallback 让代码可读性变差

我看到过一些代码,使用 useCallback 后,大概长这样:

在上面的代码中,变量依赖一层一层传递,最终要判断具体哪些变量变化会触发 useEffect 执行,是一件很头疼的事情。

我期望不要用 useCallback,直接裸写函数就好:

在 useEffect 存在延迟调用的场景下,可能造成闭包问题,那通过咱们万能的方法就能解决:

对 useCallback 的建议就一句话:没事别用 useCallback。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com