簡體   English   中英

為什么在這里使用 useMemo 而不是 useCallback?

[英]Why use useMemo and not useCallback here?

因此,據我了解,兩者之間的區別在於,如果在返回原語時返回 useMemo 時返回 function 或 object 或數組,則使用 useCallback。 但我正在查找去抖動(這是文章: https://dmitripavlutin.com/react-throttle-debounce/它說 useMemo 將是一個更好的解決方案。使用 useCallback

import { useState, useCallback } from 'react';
import debounce from 'lodash.debounce';
export function FilterList({ names }) {
  const [query, setQuery] = useState("");
  let filteredNames = names;
  if (query !== "") {
    filteredNames = names.filter((name) => {
      return name.toLowerCase().includes(query.toLowerCase());
    });
  }
  const changeHandler = event => {
    setQuery(event.target.value);
  };
  const debouncedChangeHandler = useCallback(
    debounce(changeHandler, 300)
  , []);
  return (
    <div>
      <input 
        onChange={debouncedChangeHandler} 
        type="text" 
        placeholder="Type a query..."
      />
      {filteredNames.map(name => <div key={name}>{name}</div>)}
    </div>
  );
}

用 useMemo

import { useState, useMemo } from 'react';
import debounce from 'lodash.debounce';
export function FilterList({ names }) {
  const [query, setQuery] = useState("");
  let filteredNames = names;
  if (query !== "") {
    filteredNames = names.filter((name) => {
      return name.toLowerCase().includes(query.toLowerCase());
    });
  }
  const changeHandler = (event) => {
    setQuery(event.target.value);
  };
  const debouncedChangeHandler = useMemo(
    () => debounce(changeHandler, 300)
  , []);
  return (
    <div>
      <input
        onChange={debouncedChangeHandler}
        type="text"
        placeholder="Type a query..."
      />
      {filteredNames.map(name => <div key={name}>{name}</div>)}
    </div>
  );
}

我不明白。 debounce 是否返回原始值? 如果不是,我們如何使用 useMemo? 還有這里的 useMemo 比 useCallback 好在哪里?

首先關於你的報價:

如果返回原語時返回 function 或 object 或數組,則使用 useCallback

不,這是錯誤的。 useCallback主要用於記憶函數。 useMemo有助於避免在每次渲染時進行昂貴的計算。


現在來看這篇文章。 那篇文章更喜歡useMemo的另一個原因是性能。 盡管我懷疑在大多數此類情況下性能差異會很明顯。

 const debouncedChangeHandler = useCallback(
    debounce(changeHandler, 300)
  , []);

它說:

然而......這個實現有一個小的性能問題:每次組件重新渲染時, debounce(changeHandler, 300) 創建一個去抖動 function 的新實例

也就是說,即使debouncedChangeHandler由於useCallback在重新渲染中保持不變, debounce debounce(changeHandler, 300)仍然在每次渲染時執行。

但是使用useMemo

  const debouncedChangeHandler = useMemo(
    () => debounce(changeHandler, 300)
  , []);

它聲稱:

useMemo(() => debounce(changeHandler, 300), []) 記憶去抖處理程序,但也僅在組件的初始渲染期間調用 debounce()

這就是文章更喜歡useMemo的原因。


運行此代碼:

let T1 = () => console.log('test1');
let T2 = () => console.log('test2');

export default function App() {
  let f = React.useCallback(T1(), []);
  let g = React.useMemo(() => T2(), []);
  let [x, setX] = React.useState(0);
  return (
    <div
      onClick={() => {
        setX(x + 1);
      }}
    >
      <h1>{x}</h1>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

在任意位置單擊div並查看test2如何不再記錄。

  const debouncedChangeHandler = useCallback(
    debounce(changeHandler, 300)
  , []);

在每個渲染中:

  1. debounce(changeHandler, 300)將運行(它不是 function,它是一個被調用函數)並解析為一個值(這是一個回調)
  2. 然后 useCallback 將運行,檢查依賴關系以確定它是否應該返回記憶值或新值,所以在你的情況下,它將返回記憶值
  const debouncedChangeHandler = useMemo(
    () => debounce(changeHandler, 300)
  , [])

在每次渲染中

  1. () => debounce(changeHandler, 300)不會運行,是 value(callback)
  2. 然后 useMemo 將運行,它將檢查依賴關系以確定是否運行回調,在您的情況下,它不會運行回調

如果你想返回一個值,使用useMemo如果你使用useMemo,它會產生副作用,讓代碼看起來很糟糕。 如果你想返回一個回調,使用useCallback

關於 useMemo 和 useCallback https://medium.com/@jan.hesters/usecallback-vs-usememo-c23ad1dc60之間差異的精彩文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM