简体   繁体   English

useCallback 与 useMemo 以及何时使用它们

[英]useCallback vs. useMemo and when to use them

What is the main difference between useCallback and useMemo ? useCallbackuseMemo之间的主要区别是什么? And when to use useCallback of React Hooks?什么时候使用 React Hooks 的useCallback

useMemo(() => (bar) => foo + bar, [foo]);

Equivalent code with useCallback:使用 useCallback 的等效代码:

useCallback((bar) => foo + bar, [foo]);

Use callback is just a shorthand variation of useMemo to use with functions.使用回调只是useMemo与函数一起使用的速记变体。

Here is why it exists: When you use useMemo ,the value usually changes when one of its dependencies change.这就是它存在的原因:当您使用useMemo ,该值通常会在其依赖项之一发生变化时发生变化。 For example:例如:

const fullName = useMemo(() => firstName + lastName, [firstName, lastName]);

If firstName or lastName change, fullName will also change.如果firstNamelastName更改, fullName也会更改。 On the other hand, functions themselves usually don't need to be recomputed, and their dependencies are mostly closure values that may change.另一方面,函数本身通常不需要重新计算,它们的依赖关系大多是可能会改变的闭包值。

const getFullName = useCallback(() => firstName + lastName, [firstName, lastName]);

Here, when firstName or lastName change, we don't need to have a completely different function with a different body, but we do need to have a new instance of the same function so that it has up to date values in closure (dependencies).在这里,当firstNamelastName更改时,我们不需要具有不同主体的完全不同的函数,但我们确实需要具有相同函数的新实例,以便它在闭包中具有最新值(依赖项) . So React team just added it for convenience as it is a common use case, and the () => () => syntax is somewhat ugly.所以 React 团队只是为了方便起见添加了它,因为它是一个常见的用例,而且() => () =>语法有点难看。

useMemo and useCallback both use something called memoization which you can think of it like the hooks are remembering something. useMemouseCallback都使用一种叫做记忆化,你可以像钩子记起了想起来了。


The differences:区别:

useMemo will memoize/remember the value that is returned from the function you pass into it until the dependancies change. useMemo将记住/记住您传递给它的函数返回的,直到依赖关系发生变化。

const num = 10
const result = useMemo(() => num + num, [num])
// result is now equal to 20

useCallback will memoize/remember the actual function you pass into it until the dependancies change which gives you something called referential equality . useCallback会记住/记住你传递给它的实际函数,直到依赖关系发生变化,这会给你一些称为引用相等的东西。

const num = 10
const result = useCallback(() => num + num, [num])
// result is now equal to () => num + num.
// result === result between renders.

Referential equality:参照平等:

() => {} === () => {} // This is false
const a = () => {}
a === a // This is true

Both of them take a function and an array of dependencies as parameters like 'useEffect'. 它们都将一个函数和一个依赖项数组作为参数,如'useEffect'。 The function's return value will only be changed if one of the dependencies value changes — otherwise a cached value will be returned. 只有在其中一个依赖项值发生更改时,才会更改函数的返回值 - 否则将返回缓存的值。

Note that passing an empty array of dependencies or no array at all will cause the Hook to return a memoized value on every call. 请注意,传递一个空的依赖数组或根本没有数组将导致Hook在每次调用时返回一个memoized值。

The main difference between the two is that 'useCallback' returns a memoized callback and 'useMemo' returns a memoized value that is the result of the function parameter. 两者之间的主要区别在于'useCallback'返回一个memoized回调,'useMemo'返回一个memoized值,该值是函数参数的结果。

If you have to process a lot of data, 'useMemo' is the perfect Hook as it will do the work once at the first render and then return a cached version on every other render. 如果你必须处理大量数据,'useMemo'是完美的Hook,因为它将在第一次渲染时完成一次工作,然后在每个其他渲染上返回一个缓存版本。

'useCallback', however, is used differently. 但是,'useCallback'的使用方式不同。 Take for example a parent component that often re-renders. 例如,经常重新渲染的父组件。 Inside the parent, we have a child component that takes a function-prop. 在父级内部,我们有一个带有函数prop的子组件。 At each re-render, the Child will re-execute its function prop uselessly. 在每次重新渲染时,Child将无用地重新执行其函数prop。 However, if you pass 'useCallback' as a prop with a dependency array, it resolves the issue because the function will be executed only when the dependency changes. 但是,如果将'useCallback'作为具有依赖关系数组的prop传递,它将解决该问题,因为该函数仅在依赖关系更改时才会执行。 Every other re-render will then get a cached function. 然后每个其他重新渲染都将获得一个缓存函数。

import React, { useState, useMemo, useCallback } from "react";

const App = () => {
  // We create two states that will keep count of the number of time all hooks are called
  const [callbackCount, setCallbackCount] = useState(0);
  const [memoCount, setMemoCount] = useState(0);

  const memoFunction = () => {
    console.log(memoCount, "memo called");
    // Do something that will take a lot of processing ...
  };

  // Here if we give an empty array of dependencies, the callback function will return the old value of callbackCount
  // because useCallback will return its memoized version
  const callbackFunction = useCallback(() => {
    console.log(callbackCount, "callback called");
    // Do something with callbackCount ...
    return callbackCount;
  }, [callbackCount]);

  // We create the memo hook, when memoCount changes, the function will be executed again
  useMemo(memoFunction, [memoCount]);

  return (
    <>
      {/* This component will receive a function that will change when the dependency value changes */}
      <ChildComponent action={callbackFunction} />

      {/* Change the callback hook dependency to trigger a change in the child */}
      <button onClick={() => setCallbackCount(callbackCount + 1)}>
        Change callback count
      </button>

      {/* After creating useMemo, each change of memoCount will trigger the function passed to the hook,
    otherwise the memoized value will be returned */}
      <button onClick={() => setMemoCount(memoCount + 1)}>
        Change memo count
      </button>
    </>
  );
};

const ChildComponent = ({action}) => {
  const [value, setValue] = useState(0)

  useEffect(() => {
    let val = action()
    setValue(val)
  }, [action]) 

  return(
    <>
    Child : {value}
    </>
  )
}

Now you should be ready to optimise your code with React Hooks. 现在,您已准备好使用React Hooks优化代码。 To recap: you should not use 'useCallback' and 'useMemo' for everything. 回顾一下:你不应该使用'useCallback'和'useMemo'来做所有事情。 'useMemo' should be used for big data processing while 'useCallback' is a way to add more dependency to your code to avoid useless rendering. 'useMemo'应该用于大数据处理,而'useCallback'是一种向代码添加更多依赖的方法,以避免无用的渲染。

We can use useCallback to memoize a function, which means that this function only gets re-defined if any of its dependencies in the dependency array change.我们可以使用useCallbackuseCallback一个函数,这意味着这个函数只有在依赖数组中的任何依赖发生变化时才会被重新定义。

useMemo(() => computation(a, b), [a, b]) is the hook that lets us memoize expensive computations. useMemo(() => computation(a, b), [a, b])是让我们记住昂贵计算的钩子。 Given the same [a, b] dependencies, once memoized, the hook is going to return the memoized value without invoking computation(a, b).给定相同的 [a, b] 依赖项,一旦记忆,钩子将返回记忆值而不调用计算(a,b)。

This article about different React Memoization Methods: React.memo, useMemo, useCallback, what is different between them with practical examples: https://medium.com/geekculture/great-confusion-about-react-memoization-methods-react-memo-usememo-usecallback-a10ebdd3a316本文介绍了不同的 React Memoization 方法:React.memo、useMemo、useCallback,它们之间有什么不同并附有实际示例: https ://medium.com/geekculture/great-confusion-about-react-memoization-methods-react-memo -usememo-usecallback-a10ebdd3a316

The useMemo is used to memoize values, React.memo is used to wrap React Function components to prevent re-renderings. useMemo 用于记忆值,React.memo 用于包装 React Function 组件以防止重新渲染。 The useCallback is used to memoize functions. useCallback 用于记忆函数。

useMemo helps prevent re-rendering unless dependencies to a function have changed while useCallback helps prevent rerendering unless a function has changed. useMemo有助于防止重新渲染,除非对函数的依赖项已更改,而useCallback有助于防止重新渲染,除非函数已更改。 Ie when a function is to be passed as an argument to another function, useCallback will only allow re-rendering after a different function is passed.即当一个函数作为参数传递给另一个函数时, useCallback将只允许在传递不同的函数后重新渲染。 Here is a link to a resource that might help explain further这是一个资源的链接,可能有助于进一步解释

https://btholt.github.io/complete-intro-to-react-v5/hooks-in-depth https://btholt.github.io/complete-intro-to-react-v5/hooks-in-depth

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM