![](/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.