首页 > 其他分享 >react hooks--useCallback

react hooks--useCallback

时间:2024-09-19 10:20:45浏览次数:11  
标签:count const 函数 -- hooks memo useCallback react 组件

概述

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。

标签:count,const,函数,--,hooks,memo,useCallback,react,组件
From: https://blog.csdn.net/weixin_43285360/article/details/142353421

相关文章

  • SQL注入漏洞的检测及防御,零基础入门到精通_sql 防注入检测
    SQL注入(SQLInjection)是一种广泛存在于Web应用程序中的严重安全漏洞,它允许攻击者在不得到授权的情况下访问、修改或删除数据库中的数据。这是一种常见的攻击方式,因此数据库开发者、Web开发者和安全专业人员需要了解它,以采取措施来预防和检测SQL注入漏洞。01什么是SQL注入......
  • springboot乡村旅游管理---附73081
    摘 要随着乡村旅游的蓬勃发展,传统的管理方式已难以满足日益增长的游客需求和市场变化。因此,借助现代信息技术手段,构建基于SpringBoot的乡村乡村旅游管理显得尤为重要。该系统旨在通过整合乡村旅游资源,提供智能化的管理服务,促进乡村旅游产业的健康发展,为游客提供更加优质......
  • 在AI的时代,程序员如何才不被淘汰
    随着人工智能技术的迅猛发展,大模型(LargeLanguageModels,LLMs)正逐渐成为IT行业的热点。对于程序员来说,转行大模型领域不仅意味着新的机遇,也面临着诸多挑战。本文将探讨程序员转行大模型的机遇与挑战,以及如何顺利实现转型。机遇:技术升级:大模型领域的技术不断迭代,程序员......
  • 基于SpringBoot的网上招聘系统的设计与实现---附源码72387
    目 录第1章引 言1.1选题背景1.2研究现状1.3论文结构安排第2章系统的需求分析2.1系统可行性分析2.1.1技术方面可行性分析2.1.2经济方面可行性分析2.1.3法律方面可行性分析2.1.4操作方面可行性分析2.2系统功能需求分析2.3系统性......
  • 半天玩转大模型技术之RAG
    引言当前大模型在金融行业最广泛的应用之一就是知识问答,而支撑该应用的技术正是当下火热的检索增强生成(RetrievalAugmentedGeneration)技术,简称RAG。因企业具体的业务往往需要注入特定的知识,比如ChatBI中企业数据库的相关知识、客服助手中客服FAQ等,所以RAG不仅可以应用......
  • 易优cms网站安装时数据库提示写入表ey_archives记录失败,请刷新重试
    当您在安装易优CMS时遇到“安装时数据库提示写入表ey_archives记录失败,请刷新重试”的问题时,可以尝试以下几种方法来解决:解决步骤清空数据库重新安装切换数据库版本直接导入数据库详细步骤1.清空数据库登录数据库管理工具:使用数据库管理工具(如phpMyAdmin、MySQLWo......
  • Odoo17.0 小红书
    小红书是近年来年轻人中非常流行的社交分享购物平台,本章我们将介绍如何使用我们的小红书模块来完成平台和odoo的对接。当前版本:17.0.1.0基础配置首先,我们要在系统中安装我们的小红书模块: 安装完模块之后,我们到主菜单-小红书-配置-店铺中新建一个店铺: 将我们在小红书商......
  • vue打包优化——使用webpack-parallel-uglify-plugin并行压缩JavaScript
    1、安装插件npminstallwebpack-parallel-uglify-plugin--save-dev我用的install命令,其他命令大同小异,大家百一下就行2、配置vue.config.js首先引入插件:constParallelUglifyPlugin=require('webpack-parallel-uglify-plugin');这里注意我用的vue-cli构建的项目,所以修改w......
  • 易优cms网站安装一直显示未知错误,无法继续
    当您在安装易优CMS时遇到“未知错误,无法继续”的问题,并且怀疑是由于数据库版本过高导致的,可以尝试将MySQL版本设置为5.6。以下是详细的步骤说明:解决步骤确认当前MySQL版本降级MySQL版本至5.6重新安装易优CMS详细步骤1.确认当前MySQL版本登录数据库管理工具:使用数据......
  • 易优cms网站安装报错Parse error: syntax error, unexpected '[' in /data/home/xyu80
    当您在安装易优CMS时遇到“Parseerror:syntaxerror,unexpected'['”的错误,这通常是由于PHP版本过高导致的。易优CMS可能不支持某些较新版本的PHP语法特性。您可以尝试将PHP版本设置为5.5来解决这个问题。解决步骤确认当前PHP版本降级PHP版本至5.5重新安装易优CMS详细......