精华内容
下载资源
问答
  • useCallback useMemo

    2021-03-30 10:21:37
    //useCallback function father(){ const [count, setCount] = useState(0); const handleClick = useCallback(() => { setCount1(count + 1) }, [count]); return ( <> <button onClick={...
    //useCallback
    function father(){
        const [count, setCount] = useState(0);
    
        const handleClick = useCallback(() => {
          setCount1(count + 1)
        }, [count]);
    
        return (
          <>
            <button onClick={handleClick}>{count}</button>
          </>
        )
    }
    
    //其实在这里并没有任何优化,反而在从新渲染是判断count 而增加了成本
    
    
    const Button = React.memo(({handleClick})=>{
    
        return  return (
          <>
            <button onClick={handleClick}>{count}</button>
          </>
        )
    })
    
    //如过在上面使用这样的自组件 可以优化子组件重新渲染
    //useMemo
    
    const [count, setCount] = useState(0);
    
    const userInfo = useMemo(() => {
      return {
        count: count
      };
    }, [count]);
    
    return <UserCard userInfo={userInfo}>

    useCallback 缓存的是函数与 useMemo 函数的返回就结果。

    展开全文
  • useMemo与useCallback使用指南

    万次阅读 多人点赞 2019-07-02 16:29:20
    上一篇文章介绍了useEffect的使用,接下来准备介绍useCallback和useMemo。 回顾 在介绍一下这两个hooks的作用之前,我们先来回顾一下react中的性能优化。在hooks诞生之前,如果组件包含内部state,我们都是基于...

    上一篇文章介绍了useEffect的使用,接下来准备介绍useCallback和useMemo。

    回顾

    在介绍一下这两个hooks的作用之前,我们先来回顾一下react中的性能优化。在hooks诞生之前,如果组件包含内部state,我们都是基于class的形式来创建组件。当时我们也知道,react中,性能的优化点在于:

    1. 调用setState,就会触发组件的重新渲染,无论前后的state是否不同
    2. 父组件更新,子组件也会自动的更新

    基于上面的两点,我们通常的解决方案是:使用immutable进行比较,在不相等的时候调用setState;在shouldComponentUpdate中判断前后的props和state,如果没有变化,则返回false来阻止更新。

    在hooks出来之后,我们能够使用function的形式来创建包含内部state的组件。但是,使用function的形式,失去了上面的shouldComponentUpdate,我们无法通过判断前后状态来决定是否更新。而且,在函数组件中,react不再区分mount和update两个状态,这意味着函数组件的每一次调用都会执行其内部的所有逻辑,那么会带来较大的性能损耗。因此useMemo 和useCallback就是解决性能问题的杀手锏。

    对比

    我们先简单的看一下useMemo和useCallback的调用签名:

    function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T; function useCallback<T extends (...args: any[]) => any>(callback: T, deps: DependencyList): T;

    useCallback和useMemo的参数跟useEffect一致,他们之间最大的区别有是useEffect会用于处理副作用,而前两个hooks不能。

    useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。

    useMemo

    我们来看一个反例:

    import React from 'react';
    
    
    export default function WithoutMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
    
        function expensive() {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }
    
        return <div>
            <h4>{count}-{val}-{expensive()}</h4>
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    

    这里创建了两个state,然后通过expensive函数,执行一次昂贵的计算,拿到count对应的某个值。我们可以看到:无论是修改count还是val,由于组件的重新渲染,都会触发expensive的执行(能够在控制台看到,即使修改val,也会打印);但是这里的昂贵计算只依赖于count的值,在val修改的时候,是没有必要再次计算的。在这种情况下,我们就可以使用useMemo,只在count的值修改时,执行expensive计算:

    export default function WithMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
        const expensive = useMemo(() => {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }, [count]);
    
        return <div>
            <h4>{count}-{expensive}</h4>
            {val}
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    

    上面我们可以看到,使用useMemo来执行昂贵的计算,然后将计算值返回,并且将count作为依赖值传递进去。这样,就只会在count改变的时候触发expensive执行,在修改val的时候,返回上一次缓存的值。

    useCallback

    讲完了useMemo,接下来是useCallback。useCallback跟useMemo比较类似,但它返回的是缓存的函数。我们看一下最简单的用法:

    const fnA = useCallback(fnB, [a])

    上面的useCallback会将我们传递给它的函数fnB返回,并且将这个结果缓存;当依赖a变更时,会返回新的函数。既然返回的是函数,我们无法很好的判断返回的函数是否变更,所以我们可以借助ES6新增的数据类型Set来判断,具体如下:

    import React, { useState, useCallback } from 'react';
    
    const set = new Set();
    
    export default function Callback() {
        const [count, setCount] = useState(1);
        const [val, setVal] = useState('');
    
        const callback = useCallback(() => {
            console.log(count);
        }, [count]);
        set.add(callback);
    
    
        return <div>
            <h4>{count}</h4>
            <h4>{set.size}</h4>
            <div>
                <button onClick={() => setCount(count + 1)}>+</button>
                <input value={val} onChange={event => setVal(event.target.value)}/>
            </div>
        </div>;
    }
    

    我们可以看到,每次修改count,set.size就会+1,这说明useCallback依赖变量count,count变更时会返回新的函数;而val变更时,set.size不会变,说明返回的是缓存的旧版本函数。

    知道useCallback有什么样的特点,那有什么作用呢?

    使用场景是:有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。

    import React, { useState, useCallback, useEffect } from 'react';
    function Parent() {
        const [count, setCount] = useState(1);
        const [val, setVal] = useState('');
    
        const callback = useCallback(() => {
            return count;
        }, [count]);
        return <div>
            <h4>{count}</h4>
            <Child callback={callback}/>
            <div>
                <button onClick={() => setCount(count + 1)}>+</button>
                <input value={val} onChange={event => setVal(event.target.value)}/>
            </div>
        </div>;
    }
    
    function Child({ callback }) {
        const [count, setCount] = useState(() => callback());
        useEffect(() => {
            setCount(callback());
        }, [callback]);
        return <div>
            {count}
        </div>
    }
    

    不仅是上面的例子,所有依赖本地状态或props来创建函数,需要使用到缓存函数的地方,都是useCallback的应用场景。

    多谈一点

    useEffect、useMemo、useCallback都是自带闭包的。也就是说,每一次组件的渲染,其都会捕获当前组件函数上下文中的状态(state, props),所以每一次这三种hooks的执行,反映的也都是当前的状态,你无法使用它们来捕获上一次的状态。对于这种情况,我们应该使用ref来访问。

    源代码:

    https://github.com/anymost/hooks-demo/blob/master/src/page/Memo.js​github.com

     

    https://github.com/anymost/hooks-demo/blob/master/src/page/Callback.js​github.com

    原文https://zhuanlan.zhihu.com/p/66166173

    展开全文
  • useMemo与useCallback

    2021-03-09 19:22:44
    在hooks出来之后,我们能够使用function的形式来创建包含内部state的组件。但是,使用function的形式,...因此useMemo 和useCallback就是解决性能问题的杀手锏。 对比 我们先简单的看一下useMemo和useCallback的调用签

    在hooks出来之后,我们能够使用function的形式来创建包含内部state的组件。但是,使用function的形式,失去了上面的shouldComponentUpdate,我们无法通过判断前后状态来决定是否更新。而且,在函数组件中,react不再区分mount和update两个状态,这意味着函数组件的每一次调用都会执行其内部的所有逻辑,那么会带来较大的性能损耗。因此useMemo 和useCallback就是解决性能问题的杀手锏。
    对比
    我们先简单的看一下useMemo和useCallback的调用签名:

    function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T; 
    function useCallback<T extends (...args: any[]) => any>(callback: T, deps: DependencyList): T;
    

    useCallback和useMemo的参数跟useEffect一致,他们之间最大的区别有是useEffect会用于处理副作用(副作用指的是不可预估的输出),

    useEffect(() => {
       // 处理逻辑,比如发送请求
      
      return () => {}  //处理定时器等,进行销毁操作
    }, [])
    

    //死循环等写法

    useEffect(() => {
      // 处理逻辑,比如发送请求,改变数据
      setDate()
    })
    

    而前两个hooks不能。
    useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。
    useMemo
    我们来看一个反例:

    import React from 'react';
    export default function WithoutMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
     
        function expensive() {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }
     
        return <div>
            <h4>{count}-{val}-{expensive()}</h4>
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    

    这里创建了两个state,然后通过expensive函数,执行一次昂贵的计算,拿到count对应的某个值。我们可以看到:无论是修改count还是val,由于组件的重新渲染,都会触发expensive的执行(能够在控制台看到,即使修改val,也会打印);但是这里的昂贵计算只依赖于count的值,在val修改的时候,是没有必要再次计算的。在这种情况下,我们就可以使用useMemo,只在count的值修改时,执行expensive计算:

    export default function WithMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
        const expensive = useMemo(() => {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }, [count]);
     
        return <div>
            <h4>{count}-{expensive}</h4>
            {val}
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    

    上面我们可以看到,使用useMemo来执行昂贵的计算,然后将计算值返回,并且将count作为依赖值传递进去。这样,就只会在count改变的时候触发expensive执行,在修改val的时候,返回上一次缓存的值。

    useCallback
    讲完了useMemo,接下来是useCallback。useCallback跟useMemo比较类似,但它返回的是缓存的函数。我们看一下最简单的用法:
    const fnA = useCallback(fnB, [a])
    上面的useCallback会将我们传递给它的函数fnB返回,并且将这个结果缓存;当依赖a变更时,会返回新的函数。既然返回的是函数,我们无法很好的判断返回的函数是否变更,所以我们可以借助ES6新增的数据类型Set来判断,具体如下:

    import React, { useState, useCallback } from 'react';
     
    const set = new Set();
     
    export default function Callback() {
        const [count, setCount] = useState(1);
        const [val, setVal] = useState('');
     
        const callback = useCallback(() => {
            console.log(count);
        }, [count]);
        set.add(callback);
     
     
        return <div>
            <h4>{count}</h4>
            <h4>{set.size}</h4>
            <div>
                <button onClick={() => setCount(count + 1)}>+</button>
                <input value={val} onChange={event => setVal(event.target.value)}/>
            </div>
        </div>;
    }
    

    我们可以看到,每次修改count,set.size就会+1,这说明useCallback依赖变量count,count变更时会返回新的函数;而val变更时,set.size不会变,说明返回的是缓存的旧版本函数。
    知道useCallback有什么样的特点,那有什么作用呢?
    使用场景是:有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。

    import React, { useState, useCallback, useEffect } from 'react';
    function Parent() {
        const [count, setCount] = useState(1);
        const [val, setVal] = useState('');
     
        const callback = useCallback(() => {
            return count;
        }, [count]);
        return <div>
            <h4>{count}</h4>
            <Child callback={callback}/>
            <div>
                <button onClick={() => setCount(count + 1)}>+</button>
                <input value={val} onChange={event => setVal(event.target.value)}/>
            </div>
        </div>;
    }
     
    function Child({ callback }) {
        const [count, setCount] = useState(() => callback());
        useEffect(() => {
            setCount(callback());
        }, [callback]);
        return <div>
            {count}
        </div>
    
    展开全文
  • hooks之useCallback

    2020-04-01 22:43:24
    import React, { useState, useCallback } from 'react' /** * useCallback解决的是传入子组件的函数参数过度变化导致子组件过度渲染的问题 */ function UseMemoAPI() { const [count, setCount] = useState(0)...
    import React, { useState,  useCallback } from 'react'
    
    
    /**
     * useCallback解决的是传入子组件的函数参数过度变化导致子组件过度渲染的问题
     */
    function UseMemoAPI() {
      const [count, setCount] = useState(0)
    
      // 假设什么都不依赖,子组件应该不渲染
      const click = useCallback(() => {
        console.log('click------------')
      }, [])
    
      return (
        <div>
          <button onClick={() => setCount(count + 1)}>Click ({count})</button>
          <Counter count={count}  click={click} />
        </div>
      )
    }
    
    /**
     * memo
     * 只要父组件的值不变化,子组件就没必要渲染,
     * 如果父组件传递函数情况下,可以useCallback来作为优化手段
     */
    
    const Counter = memo(function (props) {
      console.log(1111)
      return (
        <h1 onClick={props.click}>{props.count}</h1>
      )
    })
    
    export default UseMemoAPI
    
    
    展开全文
  • useCallback 之痛

    2021-01-26 16:46:50
    useCallback问题缘由 先回顾下hook之前组件的写法 class组件 export class ClassProfilePage extends React.Component<any,any>{ showMessage = ()=>{ alert('Fllowed'+ this.props.user) } ...
  • useMemo和useCallback

    2021-03-23 15:36:09
    useCallback 之前如果我们在render中定义了一个方法: render() { const {data} = this.state; const filter = data.filter(e => e.id !== 5); ... } 那么我们知道每次render都会执行filter这个方法,其实你...
  • react useCallback的用法

    2020-11-23 09:49:42
    useCallback是react中比较重要的一个hook useCallback 用来返回一个函数,在父子组件传参或者通用函数封装中,起到举足轻重的作用。 第一种用法,父子组件函数式传参 import React, { useState, useEffect, ...
  • react useCallback 的理解

    万次阅读 2019-07-01 23:05:56
    useCallback把匿名回调“存”起来 在之前版本的文档和大牛的blog中都有提到避免在component render时候声明匿名方法,因为这些匿名方法会被反复重新声明而无法被多次利用,然后容易造成component反复不必要的渲染。 ...
  • hooks当中的useCallback

    2021-03-29 15:49:24
    useCallback 的真正目的还是在于缓存了每次渲染时 inline callback 的实例,这样方便配合上子组件的 shouldComponentUpdate 或者 React.memo 起到减少不必要的渲染的作用。需要不断提醒自己注意的是,在大部分 ...
  • useCallback 可以理解为useMemo的语法糖。 主要区别是React.useMemo将调用fn函数并返回其结果,而React.useCallback将返回fn函数而不调用它。 useCallback const memoizedCallback = useCallback( () => { ...
  • useCallback和useMemo的区别;如何使用useCallback,避免无状态组件(函数式组件)的不必要渲染;一、useRef是怎么回事1.useRef的含义 useRef returns a mutable ref object whose .current property is in...
  • useMemo和useCallback是作为性能优化的,减少一些不必要的渲染 useMemo 对值的优化,如果这个值是依赖于某个值计算来的,我不希望其他state变化的时候,这个值也被重新渲染。 function Test1 (props) { const [a,...
  • 个人理解记录,如有错误 欢迎指出 在react函数式组件中定义函数 如: export default props =>...每次组件重新渲染,函数handle都会重新声明,使用useCallback后会缓存函数 export default props =>
  • Check out my React hooks introduction first, if you’re new to them. ... One React hook I sometimes use is useCallback. 我有时使用的一个React挂钩是useCallback 。 import React, { useCall...
  • 1.useCallback 作用:在依赖项发生变化的时候,返回一个新的函数引用。 需求: 1)请求数据的接口需要放在useEffect外面,因为要将该方法传递给子组件 2)在conditions发生变化时,自动执行该函数 3)只有在...
  • react函数组件为了保持引用不变,很多时候需要借助useCallback,但是useCallback强依赖于外部变量,必须传个依赖变量,万一漏传了很容易出问题。比较函数复杂时较麻烦,使用这个即可完美解决,引用不变,调用肯定是...
  • 为什么需要使用useCallback呢??,我们先来看看官网给出的解释 这里我们看到的作用就是减少子组件没必要的渲染,具体怎么去理解我们等下看例子,我在官网的基础上再加上自己的理解吧,useCallback的目的是在与缓存...
  • useMemo 功能:用来缓存数据; 应用场景:当组件内部某个数据,需要通过计算而来,且这个计算依赖于state、props数据时使用;...import React, { useState, useEffect, useCallback, useMemo } from
  • 最近在看react hooks,useState和useEffect较好理解,到useCallback和useMemo的时候,看官网不太懂,后来通过查阅资料,算是搞明白了,下面实例都是基于react-native,不过原理和react是一样的 1、useCallback ...
  • 这篇文章将讲解 useCallback, useMemo 及 React.Memo 的运行时,作用,使用场景和注意事项 useCallback() 作用 useCallback 的真正目的在于缓存了每次渲染时 inline callback 的实例 配合 shouldComponentUpdate ...
  • @React Hook ---- useCallback详解 React Hooks 学习之 useCallback实践 前言: Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 本文主要介绍React中内置的...
  • React,Hooks中UseCallback的使用

    千次阅读 2020-07-29 23:07:13
    useCallback:是为了性能的优化 1.useCallback会返回一个函数的memoized(记忆的)值 2.在依赖不变的情况下,多次定义的时候,返回的值是相同的 先说一下useCallback不能做的性能优化 import React, { useState, ...
  • 一个简单的React Hook,将useState和useCallback连接起来。 描述:有时您只需要创建一个状态和一个useCallback函数来处理它。 useHandleState使您可以同时创建两者。 例子 没有useHandleState: import { ...
  • react中useCallback的使用

    千次阅读 2020-08-05 09:50:18
    1、参数:callback(函数),要做的事放在这个函数里面 desp:要做的事需要引入... 例:const handleChildrenCallback=useCallback(()=>{ handleChildren();//要做的事 },[]);//不需要参数就不传 2、返回值...
  • useCallback 目录 Parent.js import React, { useCallback, useState } from "react"; import Son from "./Son"; const Parent = () => { const [show, setShow] = useState(true); // 返回一个地址,只有当...
  • 一、useCallback和useMemo是什么? useCallback和useMemo是十个hook中唯二的两个不做其他操作,只做性能优化的两个hook。 二、这两个hook是为了解决什么问题? function组件和class组件性能优化其实要优化的点是类似...
  • React Hooks: useCallback理解

    千次阅读 2019-10-08 11:32:29
    useCallback把匿名回调“存”起来 避免在component render时候声明匿名方法,因为这些匿名方法会被反复重新声明而无法被多次利用,然后容易造成component反复不必要的渲染。 在Class component当中我们通常将回调...
  • 目录前言一、example1.1 useCallback1.2 useMeno总结 前言 这里主要讲讲React中两个类似的hook,useCallback以及useMeno的区别,简单来讲就是 useMeno是内部返回的一个值 useCallback是内部返回的一个当前函数 – ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 736
精华内容 294
关键字:

usecallback