![](/img/trans.png)
[英]Error: React Hook "useCallback" is called conditionally. React Hooks must be called in the exact same order in every component render
[英]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.useCallback
与lodash.memoize
和最终的结果将是几乎相同lodash.memoize
这样的外部库或构建自定义的记忆实现,而React.useCallback
几乎为我完成了工作这是我不确定发生了什么的地方(这些是我的问题)-
lodash.memoize
它们React.useCallback
React 组件时, lodash.memoize
和React.useCallback
不一样React.memo
React 也会在确定渲染之前执行该函数(也许是为了检查 prevProps 与 newProps?)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.