繁体   English   中英

即使它违反了钩子的规则,useCallback React 钩子也可以有条件地使用吗?

[英]Can the useCallback React hook be used conditionally even if it breaks the rules of hooks?

我试图找出一种方法来通过指定特定的道具来记忆 React 组件

例如,如果你使用React.memo它会根据所有的 props 来记忆组件。

我想要实现的是能够将特定道具作为依赖项传递给 util(例如SuperMemo ),并且组件将根据这些道具进行记忆。 该方法与重构非常相似——在导出之前组合组件。

这是一个示例代码

import React from "react";

const isFunction = value =>
  value &&
  (Object.prototype.toString.call(value) === "[object Function]" ||
    "function" === typeof value ||
    value instanceof Function);

export const memo = (Comp, resolver) => {
  if (isFunction(resolver)) {
    const Memoized = props => {
      const deps = resolver(props);
      if (deps && deps.length) {
        // eslint-disable-next-line react-hooks/rules-of-hooks
        return React.useCallback(React.createElement(Comp, props), deps);
      }

      return React.createElement(Comp, props);
    };

    Memoized.displayName = `memoized(${Comp.name})`;
    return Memoized;
  }

  return React.memo(Comp);
};

export default memo;

以下是它将如何用于组合组件

import Todo from "./Todo";
import memo from "../memo";

export default memo(Todo, props => [props.text]);

我这里有一个可用的代码和盒子 — memo-deps

这是我观察到的——

  • 我不应该在条件语句中使用React.useCallback或任何钩子,因为 React 需要知道调用钩子的顺序,并且在条件语句中使用它可能会在运行时弄乱顺序
  • 但是React.useCallback在我的情况下在条件下工作得非常好,因为我知道顺序在运行时将保持不变
  • 我在渲染过程中没有在条件语句中使用钩子,而是在有条件的导出过程中组合组件
  • 我正在考虑将 React 组件视为普通的 JavaScript 函数,并尝试像记住常规 JavaScript 函数一样记住它
  • 我可以很容易地更换React.useCallbacklodash.memoize和最终的结果将是几乎相同
  • 我不想使用像lodash.memoize这样的外部库或构建自定义的记忆实现,而React.useCallback几乎为我完成了工作

这是我不确定发生了什么的地方(这些是我的问题)-

  • React 组件并不是真正普通的 JavaScript 函数,我无法使用lodash.memoize它们
  • 当我尝试React.useCallback React 组件时, lodash.memoizeReact.useCallback不一样
  • 即使使用React.memo React 也会在确定渲染之前执行该函数(也许是为了检查 prevProps 与 newProps?)
  • 即使我的实现违反了 React 的规则,它是否还可以? (在条件语句中使用钩子)
  • 如果不是React.useCallback我还能如何React.createElement React.useCallback

至于我为什么要这样做的原因——

我不想在每次将处理程序传递给封装在React.memo的组件时React.memo处理程序(带有值和事件的闭包)。 我希望能够以声明方式为组件编写 memoize 依赖项。

React.memo接受一个函数作为第二个参数来进行自定义道具比较。

默认情况下,它只会浅比较 props 对象中的复杂对象。 如果您想控制比较,您还可以提供自定义比较函数作为第二个参数。

您可以在您的 util 函数中使用它,如下所示:

export const memoWithSecondParam = (Comp, deps = []) => {
  return React.memo(Comp, (prevProps, nextProps) => {
    return deps.every(d => prevProps[d] === nextProps[d])
  });
};

并这样称呼它:

export default memoWithSecondParam(Todo, ["text"]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM