React 钩子 useCallback 与循环内的参数

IT技术 reactjs react-hooks
2021-05-16 05:37:47

我正在尝试了解钩子功能,但是我似乎不太清楚我应该如何useCallback正确使用该功能据我了解钩子的规则,我应该称它们为顶级而不是在逻辑中(例如循环)。这让我很困惑我应该如何useCallback在从循环呈现的组件上实现

看看下面的示例代码片段,其中我创建了 5 个按钮,其中包含一个onClick将按钮编号打印到控制台处理程序。

const Example = (props) => {
  const onClick = (key) => {
    console.log("You clicked: ", key);
  };
  
  return(
    <div>
      {
        _.times(5, (key) => {
          return (
            <button onClick={() => onClick(key)}>
              {key}
            </button>
          );
        })
      }
    </div>
  );
};
console.log("hello there");

ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id='root'>
</div>

现在,由于我在 中使用了箭头函数<button onClick={() => onClick(key)}>每次示例呈现时它都会创建一个新的函数实例,我这样做是因为我希望onClick函数知道哪个按钮调用了它。我想我可以通过使用新的react-hooks功能来防止这种情况useCallback,但是如果我将它应用到const onClick然后它仍然会在每次渲染时创建一个新实例,因为需要提供key参数的内联箭头函数,我不允许据我所知,将它应用于循环内的渲染(特别是如果循环顺序可能会改变?)。

那么我将如何useCallback在保持相同功能的同时在这种情况下实现呢?有可能吗?

1个回答

这里的简单答案是,您可能不应该useCallback在这里使用重点useCallback是将相同的函数实例传递给优化的组件(例如PureComponentReact.memo化组件)以避免不必要的重新渲染。

在这种情况下(或大多数情况下,我怀疑)您没有处理优化的组件,因此实际上没有理由记住像 with useCallback.


假设记忆很重要,但是,这里最好的解决方案可能是使用单个函数而不是五个:而不是每个按钮的唯一函数带有keyby 闭包,您可以将 the 附加key到元素:

<button data-key={key}>{key}</button>

然后从event.target.dataset["key"]单击处理程序内部读取密钥


话虽如此,可以在一个钩子中记住多个函数。 useCallback(fn, deps)等价于useMemo(() => fn, deps)useMemo可用于同时记忆多个函数:

const clickHandlers = useMemo(() => _.times(5, key => 
  () => console.log("You clicked", key)
), [/* dependencies */]);

也许在某些情况下这很有用,但在这种情况下,我要么不理会它(而不用担心优化),要么为每个按钮使用一个处理程序。