首页 > 其他分享 >useMemo, useCallback, useEffect 三者区别

useMemo, useCallback, useEffect 三者区别

时间:2023-04-24 18:00:38浏览次数:39  
标签:const 函数 useMemo useCallback props 组件 useEffect

useMemo

  • 父组件将一个 【值】 传递给子组件,若父组件的其他值发生变化时,子组件也会跟着渲染多次,会造成性能浪费; useMemo是将父组件传递给子组件的值缓存起来,只有当 useMemo中的第二个参数状态变化时,子组件才重新渲染
  • useMemo便是用于缓存该函数的执行结果,仅当依赖项改变后才会重新计算
修改后如下,注意useMemo缓存的是函数执行的结果, 只有当[count, price]改变时才会重走一遍

const Parent = () => {
    const [count, setCount] = useState(0);
    const [color,setColor] = useState("");
    const [price,setPrice] = useState(10);
    const handleClick = () => {
        setCount(count + 1);
    }
    const getTotal = useMemo(()=>{
        console.log("getTotal exec ...") 
        return count * price
    },[count, price])
    
    return (<div>
        <div> <input onChange={(e) => setColor(e.target.value)}/></div>
        <div> <input value={price}  onChange={(e) => setPrice(Number(e.target.value))}/></div>
        <div> {count} <button onClick={handleClick}>+1</button></div>
        <div> {getTotal}</div>
    </div>)
}
复制代码

memo

  • 父组件name属性或text属性变化都会导致Parent函数重新执行,所以即使传入子组件props没有任何变化,甚至子组件没有依赖于任何props属性,都会导致子组件重新渲染
  • 使用memo包裹子组件时,只有props发生改变子组件才会重新渲染,以提升一定的性能
const Child = memo((props: any) => {
    console.log("子组件更新..."); // 只有当props属性改变,name属性改变时,子组件才会重新渲染
    return (
        <div>
            <h3>子组件</h3>
            <div>text:{props.name}</div>
            <div>{new Date().getTime()}</div>
        </div>
    )
})


const Parent = () => {
    const [text, setText] = useState("")
    …… ……
    <Child name ={text}/>
}
复制代码
  • 使用memoAPI来缓存组件
import React, { memo } from "react"
const CacheComponent = memo(() => {
  return <div> ^^ </div>  
})
复制代码

useCallback

  • 父组件将一个【方法】传递给子组件,若父组件的其他状态发生变化时,子组件也会跟着渲染多次,会造成性能浪费; usecallback是将父组件传给子组件的方法给缓存下来,只有当 usecallback中的第二个参数状态变化时,子组件才重新渲染
  • 但如果传入的props包含函数,父组件每次重新渲染都是创建新的函数,所以传递函数子组件还是会重新渲染,即使函数的内容还是一样,我们希望把函数也缓存起来,于是引入useCallback
const Child = memo((props: any) => {
    console.log("子组件更新..."); // 父级Parent函数有东西变化,Child重新执行,handleInputChange已经指向新的函数实例,所以子组件依然会刷新
    return (
        <div>
            <div>text:{props.name}</div>
            <div> <input onChange={props.handleInputChange} /></div>
        </div>
    )
})
const Parent = () => {
    const [text, setText] = useState("")
    const [count, setCount] = useState(0)
    const handleInputChange =useCallback((e) => {
         setText(e.target.value )
    },[]) 
    return (<div>
            …… ……
        <Child name={text} handleInputChange={handleInputChange}/>
    </div>)
}
复制代码
  • useCallback用用于缓存函数,只有当依赖项改变时,函数才会重新执行返回新的函数对于父组件中的函数作为props传递给子组件时,只要父组件数据改变,函数重新执行,作为props的函数也会产生新的实例,导致子组件的刷新使用useCallback可以缓存函数。需要搭配memo使用
1 - 在Parent组件里 handleInputChange用useCallback 包裹起来
2 - 当前 handleInputChange 不依赖与任何项,所以handleInputChange只在初始化的时候调用一次函数就被缓存起来

const handleInputChange =useCallback((e) => {
     setText(e.target.value )
},[]) 

3 - 将count加入到依赖项,count变化后重新生成新的函数,改变函数内部的count值
const handleInputChange =useCallback((e) => {
     setText(e.target.value )
},[count]) 
复制代码

useEffect 和 useMemo 区别

  • useEffect是在DOM改变之后触发,useMemo在DOM渲染之前就触发
  • useMemo是在DOM更新前触发的,就像官方所说的,类比生命周期就是[shouldComponentUpdate]
  • useEffect可以帮助我们在DOM更新完成后执行某些副作用操作,如数据获取,设置订阅以及手动更改 React 组件中的 DOM 等
  • 不要在这个useMemo函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo
  • 在useMemo中使用setState你会发现会产生死循环,并且会有警告,因为useMemo是在渲染中进行的,你在其中操作DOM后,又会导致触发memo

useCallback 和 useMemo 区别

  • 类似 shouldComponentUpdate, 判定该组件的 props 和 state 是否有变化,从而避免每次父组件render时都去重新渲染子组件
  • useCallback返回一个函数,当把它返回的这个函数作为子组件使用时,可以避免每次父组件更新时都重新渲染这个子组件,子组件一般配合 memo 使用
const renderButton = useCallback(
     () => (
         <Button type="link">
            {buttonText}
         </Button>
     ),
     [buttonText]    // 当buttonText改变时才重新渲染renderButton
);
复制代码
  • useMemo返回的的是一个值,用于避免在每次渲染时都进行高开销的计算
const result = useMemo(() => {
    for (let i = 0; i < 100000; i++) {
      (num * Math.pow(2, 15)) / 9;
    }
}, [num]);
复制代码

什么时候用useCallback和useMemo进行优化

链接 :技术来源程序员客栈的前端人

  • 我觉得任何时候都用是一个好的习惯,就算有比对代价也比较小,因为哪怕是对象也只是引用比较
  • React 的工作方式遵循纯函数,特别是数据的 immutable,因此,使用 memo 很重要

标签:const,函数,useMemo,useCallback,props,组件,useEffect
From: https://www.cnblogs.com/EQ1024/p/17350363.html

相关文章

  • react useMemo
    useMemo是React提供的一个用于优化组件性能的钩子函数。它可以缓存组件的计算结果,并在依赖项发生变化时重新计算。这可以避免在每次组件渲染时都重新计算相同的值,从而提高组件的性能。useMemo的语法如下:constmemoizedValue=useMemo(()=>computeExpensiveValue(a,b),......
  • react useCallback
    useCallback是一个ReactHooksAPI,它可以用于优化函数组件的性能,避免不必要的重新渲染。useCallback接受两个参数:第一个参数是一个回调函数,第二个参数是一个依赖数组,用于控制何时重新创建回调函数。当依赖数组中的任何一个值发生变化时,useCallback将返回一个新的回调函数。否......
  • react useEffect的用法
    useEffect是ReactHook的一种,用于在函数组件中定义副作用操作,比如改变DOM、发送网络请求、订阅事件等等。useEffect用于替代类组件中的生命周期方法。它接受一个函数作为第一个参数,在组件更新时调用这个函数,如果你需要在组件挂载时调用这个函数,需要传入一个空数组作为第二个参数;如......
  • 初学React useEffect Hook
    ReactHooks是从功能组件访问React的状态和生命周期方法的最佳方式。​​useEffect​​​Hook是一个在渲染之后和每次DOM更新时运行的函数(效果)。在本文中,将讨论一些......
  • useCallback
    useCallbackisaReactHookthatletsyoucacheafunctiondefinitionbetweenre-rendersconstcachedFn=useCallback(fn,dependencies)ReferenceuseCallback(......
  • React之useEffect简记
    一.作用useEffectHook相当于componentDidMount,componentDidUpdate和componentWillUnmount这三个reactclass的生命周期函数的组合。componentDidMount:组件挂载;compone......
  • hook useRef,useState,父传子,useReducer,@observable,useCallback
    //返回一个可变的ref对象,该对象只有个current属性,初始值为传入的参数(id??'')。constactiveMenuKeyRef=useRef<string|number>(id??''); key[0]......
  • 详细解读 React useCallback & useMemo
    前言阅读本文章需要对Reacthooks中useState和useEffect有基础的了解。我的这篇文章内有大致介绍在React项目中全量使用Hooks。useCallbackuseCallback的作......
  • useEffect的使用
    例子import{GridContent,PageContainer}from'@ant-design/pro-layout';import{Card}from'antd';importReact,{useEffect,useState}from'react';importIt......
  • useLayoutEffect 和 useEffect 的区别
    useEffect和useLayoutEffect作为组件的副作用,本质上是一样的。共用一套结构来存储effect链表。整体流程上都是先在render阶段,生成effect,并将它们拼接成链表,存到fiber.upda......