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

Ant*_*Min 2 javascript anonymous-function reactjs react-hooks usecallback

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

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

import React, { useState } from 'react';

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

  return (
    ...
    <SomeComponent
      onClick={() => setParam('parameter')}
      {...others}
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

在转换匿名函数以使用此钩子的过程中,我遇到了一个错误,提示“渲染次数过多”或者它无法正常工作。但具体是在什么情况下、什么情况下我也不清楚。

我用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}
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

但是,当使用匿名函数在 内返回时useCallback,它也有效。

这意味着像这里这样的代码。(仅与上面的代码相比有所不同。)

  const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);
Run Code Online (Sandbox Code Playgroud)

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

Ayy*_*llu 5

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

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );
Run Code Online (Sandbox Code Playgroud)

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

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

const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);
Run Code Online (Sandbox Code Playgroud)

更好的方法应该如下所示,

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

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

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

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick}
      {...others}
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

回到你的问题,性能比较取决于组件内返回函数内的其他函数定义和子组件的渲染时间。假设您的应用程序中有另一个名为“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}
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

在上面的组件中,当任何一个“SomeCompoenent”单击整个“组件”时,都会重新渲染,因此处理程序函数是新定义的。并且当两者都对 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}
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

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

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

何时使用 useMemo 或 useCallback参考此