关于useCallback钩子和匿名函数的问题

Questions about useCallback hook and anonymous function

传递回调函数时,尤其是传递 参数化 函数时,我知道我应该使用 useCallback 挂钩,因为使用匿名函数会产生不利影响性能。

我说的匿名函数的例子是这样的

import React, { useState } from 'react';

const Component = () => {
  const [param, setParam] = useState('');
  ...

  return (
    ...
    <SomeComponent
      onClick={() => setParam('parameter')}
      {...others}
    />
  );
}

在将匿名函数转换为使用此钩子的过程中,我遇到了一个错误'Too many renders'或者没有正常工作。 但是具体是在什么情况下,在什么情况下我也不清楚

我使用了如下的 useCallback

import React, { useState, useCallback } from 'react';

const Component = () => {
  const [param, setParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );
}

然而,当在 useCallback 中使用匿名函数 return 时,它也有效。

这意味着这里的代码。 (仅与上述代码相比的差异。)

  const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);

在这种情况下,我想知道如果我只是使用匿名函数而不是使用这个钩子,是否比在 useCallback 中使用匿名函数更糟糕。

在您的代码中:

const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

您应该像这样将参数传递到 useCallback 的第二个参数中:

const handleClick = useCallback((params) => {
    setParam(params);
  },[setParam,param, SETPARAMACTUALVALUE]); 
// Change SETPARAMACTUALVALUE to whatever the variable name is for the `setParam` hook

useCallback hook 如果你想在 hook 的依赖关系改变之前保存函数会更好。它为您提供更好的性能,因为挂钩会记住内部函数。

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );

在上面的代码中,在第一次渲染期间,在这个语句 "onClick={handleClick('parameter')}" handleClick 函数中调用了一个名为 "parameter" 的字符串。因为 handleClick 有 setParam("parameter"),它会更新状态。更新状态将导致重新渲染,这将再次出现相同的语句 "onClick={handleClick('parameter')}" 导致无限循环。

您稍后添加的以下代码可以工作,因为您没有更新状态,而是 return 调用一个函数,该函数充当 onclick 处理程序。

const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);

更好的方法如下,

import React, { useState, useCallback } from 'react';

const Component = () => {
  const [param, setParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick}
      {...others}
    />
  );
}

回到您的问题,比较性能取决于其他函数定义和 您组件内 return 函数内的子组件 的渲染时间。 假设您的应用程序中有另一个名为 'anotherHandleClick' 的 onclickHanldier。 那么你的组件看起来像这样

const Component = () => {
  const [param, setParam] = useState('');
  const [anotherParam, setAnotherParam] = useState('');

  const handleClick = (params) => {
    setParam(params);
  };
const anotherHandleClick =(params) => {
    setAnotherParam(params);
  };
  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
<SomeComponent
      onClick={antherHandleClick('parameter')}
      {...others}
    />
  );
}

在上面的组件中,当 "SomeCompoenent" 中的任何一个被点击时,整个 "Component" 重新渲染,所以处理函数是新的 defined.and 当两者都对 onclick 进行引用相等性检查时处理函数,他们认为是新的处理函数使他们同时呈现两者。 在这种情况下,最好使用 useCallBack 钩子,如下所示,

const Component = () => {
  const [param, setParam] = useState('');
      const [anotherParam, setAnotherParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);
const anotherHandleClick = useCallback((params) => {
    setAnotherParam(params);
  },[]);
  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
<SomeComponent
      onClick={antherHandleClick('parameter')}
      {...others}
    />
  );
}

在上面的代码中,当任何一个被点击时,状态都会改变。然后在渲染时,useCallback 确保 onclick 处理程序引用没有改变。因此不会重新呈现对 onclick 处理程序的依赖。

所以最后的想法是 它在两种情况下都在每个渲染器上创建一个函数。第二个(因为它被包装在 useCallback 中)将 return 在初始渲染时创建的记忆函数

何时使用 useMemo 或 useCallback refer this