首页 > 其他分享 >react_hooks系列 useCallback,高阶函数memo

react_hooks系列 useCallback,高阶函数memo

时间:2023-12-12 22:34:47浏览次数:27  
标签:count 函数 hooks memo SonFn useCallback 组件

react_hooks的useCallback,高阶函数memo
一、概念和作用
1、memo高阶函数:
memo解决的是函数式组件的无效渲染问题,当函数式组件重新渲染时,会先判断数据是否发生了变化。相当于类组件的PureComponent(默认提供ShouldComponentUpdate)

2、useCallback:

1)、useCallback会返回一个函数的memoized(记忆的)值

2)、在依赖不变的情况下,多次定义(如:函数)的时候,返回的值是相同的 。

3)、格式:let 新的函数 = useCallback(曾经的函数, [依赖的值])

 

二、使用场景:
1、memo高阶函数的使用场景:
不论父组件是什么类型的组件,子组件是否渲染 :

1)、 如果子组件是类组件(继承自PureComponent)
​ 那么是否渲染由props和state是否改变决定;

2)、如果子组件是函数式组件
​ 只要父组件渲染,子组件会无条件渲染。如下是代码示例:

//父组件:
import { useState } from "react";
import SonFn from "./SonFn";

export default () => {
    console.log("父组件");
    const [count, setCount] = useState(1);

    let changeCount = () => {
        setCount(count + 1);
   }
    return (
        <>
            <h1>useCallback</h1>
            <p>{count}</p>
            <input type="button" value="修改count" onClick={changeCount} />
            <hr />
            <SonFn />
        </>
    )
}
//子组件:
./SonFn.js

export default ()=>{
    console.log("子组件");
    return (
        <div>
            <h5>子组件(函数式组件)</h5>
        </div>
    )
}   

只要点击按钮"修改count”,父组件就会刷新,而子组件SonFn也会无条件渲染(这是无效的渲染)。

3)、解决方案:
​ 把子组件用高阶函数memo进行包裹,就能解决子组件的无条件渲染问题,即:子组件的渲染就会由props和state决定,有点像类组件继承自PureComponent的感觉。

如下是代码(只需要把子组件的代码进行修改就行):

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

const SonFn = ()=>{
    console.log("子组件");
    return (
        <div>
            <h5>子组件(函数式组件)</h5>
        </div>
    )
}

export default memo(SonFn);
2、useCallback的使用场景:

父组件是函数式组件,子组件也是函数式组件(并且用memo包裹)

1)、子组件的属性是数据:

​ 如果数据不变化,那么子组件不渲染,如果数据发生变化,那么子组件渲染。这里就没有性能问题。

//父组件

import { useState,useCallback } from "react";
import SonFn from "./SonFn";

export default () => {
    console.log("父组件UseCallback");
    const [count, setCount] = useState(1);

    let changeCount = () => {
        setCount(count + 1);
    }

    return (
        <>
            <h1>useCallback1</h1>
            <p>{count}</p>
            <input type="button" value="修改count" onClick={changeCount} />
            <hr/>
            {/*此处给子组件传入了数据count,count只要发生变化,子组件就会重新渲染*/}
            <SonFn count={count} />
        </>
    )
}

//子组件:
./SonFn.js

import React,{memo} from 'react'

const SonFn = ({count})=>{
    console.log("子组件");
    return (
        <div>
            <h5>子组件(函数式组件)</h5>
            <p>{count}</p>
        </div>
    )
}

export default memo(SonFn);
2)、子组件的属性是函数时,就会出现问题:

​ 父组件刷新了,子组件依然会刷新。因为,父组件(函数式)每次刷新时,函数都会重新定义,那么传给子组件的函数属性必然会发生变化。所以子组件会刷新,如下是示例代码:

//父组件:

import { useState } from "react";
import SonFn from "./SonFn";

export default () => {
    console.log("父组件");
    const [count, setCount] = useState(1);
    let changeCount = () => {
        setCount(count + 1);
    }
    let increment = ()=>{
        console.log("increment");
    }
    return (
        <>
            <h1>useCallback</h1>
            <p>{count}</p>
            <input type="button" value="修改count" onClick={changeCount} />
            <hr/>
            <SonFn onMyClick={increment} />
        </>
    )
}

//子组件:
./SonFn.js

import React,{memo} from 'react'
const SonFn = ()=>{
    console.log("子组件");
    return (
        <div>
            <h5>子组件(函数式组件)</h5>
        </div>
    )
}
export default memo(SonFn);
3)、解决方案:把传给子组件的函数属性,用useCallback包裹。

格式:let 新的函数 = useCallback(曾经的函数, [依赖的值])

如下是修改后的代码(只需要修改父组件的代码):

以下代码把increment函数进行了包裹

export default () => {
    console.log("父组件");
    const [count, setCount] = useState(1);

    let changeCount = () => {
        setCount(count + 1);
    }

    let increment = useCallback(()=>{
        console.log("increment");
    },[]) // 该函数永远不会重新定义(没有依赖)
    
    /*
    let increment = useCallback(()=>{
        console.log("increment");
    },[count]) // 当count的值发生变化是,该函数才会重新定义
    */
    return (
        <>
            <h1>useCallback</h1>
            <p>{count}</p>
            <input type="button" value="修改count" onClick={changeCount} />
            <hr/>
            <SonFn onMyClick={increment} />
        </>
    )
}
三、总结:

1、“万恶之源” :函数式组件每次重新渲染时,都会把函数体里的所有代码执行一遍。

2、useCallback解决的是 防止函数式组件里的 子函数(闭包) 多次被定义。既就是:useCallback是保证函数式组件重新渲染时,组件里的函数(闭包)只被定义一次!

标签:count,函数,hooks,memo,SonFn,useCallback,组件
From: https://www.cnblogs.com/limou956259/p/17898001.html

相关文章

  • React Hooks 钩子特性
    人在身处逆境时,适应环境的能力实在惊人。人可以忍受不幸,也可以战胜不幸,因为人有着惊人的潜力,只要立志发挥它,就一定能渡过难关。Hooks是React16.8的新增特性。它可以让你在不编写class组件的情况下使用state以及其他的React特性。ReactHooks表现形式是以use开头......
  • react_hooks系列 useState
    一、作用:useState让函数式组件也可以处理状态。二、格式:1、定义状态:const[状态名,更新状态的函数]=React.useState(初始值|函数);​如:1)、基本类型的状态声明一个新的叫做“count”的state变量,初始值为0。​const[count,setCount]=React.useState(0);//useS......
  • react_hooks系列 useEffect
    一、作用​可以使得你在函数组件中执行一些带有副作用的方法。​每当React组件更新之后,就会触发useEffect,在第一次的render和每次update后的useEffect触发,不用再去考虑“初次挂载”还是“更新”。React保证了每次运行effect的同时,DOM都已经更新完毕。......
  • Linux kernel memory barriers 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/core-api/wrappers/memory-barriers.htmlLinux内核内存屏障免责声明本文档不是一个规范;它故意(为了简洁)和无意(因为是人类)不完整。本文档旨在指导如何使用Linux提供的各种内存屏障,但如果有任何疑问(而且有很多),请咨询。一些疑问可能通过参......
  • 无涯教程-Erlang - memory函数
    返回一个列表,其中包含有关由Erlang动态分配的内存的信息,该列表的每个元素都是一个元组{Type,Size},第一个元素Type是描述内存类型的原子。memory-语法memory()memory-返回值返回一个列表,其中包含有关由Erlang仿真器动态分配的内存的信息。-module(helloLearnfk).-export......
  • kettle从入门到精通 第二十三课 kettle carte 错误(java.lang.OutOfMemoryError: GC ov
     1、Couldnotemitbufferduetolackofrequests(无法发出缓冲区,因为请求不足。)原因有两点:1)消费者处理数据能力较弱,如表输出步骤。2)消费者没有处理数据,如传递的数据中有字段type=1的数据,这种情况没有处理。解放方案:针对1)采用多线程处理和开启批量提交,如下图所示批量插入......
  • vue3 之 封装hooks
    注意:使用Hooks来做的话,需要封装一个以use开头的函数,自定义Hooks有一个潜规则,就是要use开头一、相关链接①已经封装好可直接使用的:https://vueuse.org/core/useMounted/② 为什么要在Vue3中多使用Hooks?好处是啥?: https://zhua......
  • The IDE is running low on memory
    WebStorm内存不足提示:TheIDEisrunninglowonmemoryandthismightaffectperformance.Pleaseconsiderincreasingtheheapsize.翻译:IDE内存不足,这可能会影响性能。请考虑增加堆大小。手动改大......
  • Physical Memory (翻译 by chatgpt)
    原文:https://www.kernel.org/doc/html/latest/mm/physical_memory.htmlLinuxisavailableforawiderangeofarchitecturessothereisaneedforanarchitecture-independentabstractiontorepresentthephysicalmemory.Thischapterdescribesthestructures......
  • 应用报错:java.lang.OutOfMemoryError: unable to create new native thread
    上个月生产环境忽然出现部分交易处理缓慢甚至超时,查看对应应用日志发现一直在刷报错日志,报错信息如下java.lang.OutOfMemoryError:unabletocreatenewnativethread从报错上来看是说不能创建本地线程了,应用都是容器部署的,开始我怀疑是容器内存不够了导致内存泄露,但经过查看容器......