簡體   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