React Hooks:有没有理由忽略useEffect和useCallback的创建或回调是坏的?

问题描述 投票:0回答:1

所以我正在阅读Dan Abramov和"A complete Guide to useEffect"Hooks docs

在文章中,Dan给出了以下示例:

function SearchResults() {
  const [query, setQuery] = useState('react');

  // ✅ Preserves identity until query changes
  const getFetchUrl = useCallback(() => {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }, [query]);  // ✅ Callback deps are OK

  useEffect(() => {
    const url = getFetchUrl();
    // ... Fetch data and do something ...
  }, [getFetchUrl]); // ✅ Effect deps are OK

  // ...
}

Hook文档给出了这个:

function ProductPage({ productId }) {
  // ✅ Wrap with useCallback to avoid change on every render
  const fetchProduct = useCallback(() => {
    // ... Does something with productId ...
  }, [productId]); // ✅ All useCallback dependencies are specified

  return <ProductDetails fetchProduct={fetchProduct} />;
}

function ProductDetails({ fetchProduct })
  useEffect(() => {
    fetchProduct();
  }, [fetchProduct]); // ✅ All useEffect dependencies are specified
  // ...
}

我想知道:回调和工厂功能真的有必要吗?

你也可以这样写:

const getFetchUrl = useCallback('https://hn.algolia.com/api/v1/search?query=' + query, [query]);

useEffect(fetchProduct, [fetchProduct]);

同样,你可以想到一个场景,你可以将创建函数留给useMemo

function Greeting({ name }) {
  const calculateExpensive = useCallback(() => {
    return `Hello ${name}`;
  }, [name]);

  const result = useMemo(calculateExpensive, [calculateExpensive]);
  return <p>{result}</p>;
}

我确定我在这里犯了一个愚蠢的错误。我没有看到什么,做错了什么?

reactjs react-hooks
1个回答
1
投票

使用useCallback的原因是在需要时对渲染之间的函数保持相同的引用。

正如顾名思义,useCallback应该接受回调函数作为参数。由于useCallback(fn)useMemo(() => fn)的捷径,因此技术上可以(错误地)与任何参数一起使用:

const getFetchUrl = useCallback('https://hn.algolia.com/api/v1/search?query=' + query, [query]);

这样做没有任何好处,因为useMemouseCallback用于懒惰评估,而这导致了急切的评估。

使用getFetchUrl回调的示例不是很具说明性,因为memoization没有提供任何改进,它可以简化为:

function SearchResults() {
  const [query, setQuery] = useState('react');

  const fetchUrl = 'https://hn.algolia.com/api/v1/search?query=' + query;

  useEffect(() => {
    // ... Fetch data and do something ...
  }, [fetchUrl]);
}

至于Greeting的例子,useCallback是多余的。如果计算非常昂贵且需要进行懒惰评估(在本例中不是),这就是useMemo的用途:

function Greeting({ name }) {
  const result = useMemo(() => {
    return `Hello ${name}`;
  }, [name]);

  return <p>{result}</p>;
}
© www.soinside.com 2019 - 2024. All rights reserved.