Реагирует на правило ESLint исчерпывающе-deps включает предупреждение массива deps для пользовательских хуков - PullRequest
0 голосов
/ 22 января 2020

Есть ли способ сообщить правилу react-hooks/exhaustive-deps ESLint, чтобы он предупреждал меня об использовании моего пользовательского хука с отсутствующим deps? Например:

function useCustomHook(callback, deps) {
    ...
    useMemo(() => ..., deps);
    ...
}

// When using useCustomHook in a component:
function Component({ dep1, dep2, dep3 }) {
    const res = useCustomHook(
        () => dep1 + dep2 + dep3,
    []); // Even if this is a custom hook,
         // I would like exhaustive-deps to warn me
         // and tell me that I need to pass `dep1`, `dep2` and `dep3`
         // to the deps array...
    ...
}

Другой пример:

У меня есть следующий пользовательский хук, который я использую для реализации абстрактных фабрик в функциональных компонентах React:

/**
 * Usage:
 * 
 *     const choice1 = {
 *         color: "red",
 *         label: "Fire"
 *     };
 * 
 *     const choice2 = {
 *         color: "green",
 *         label: "Grass"
 *     }
 * 
 *     const choice3 = {
 *         color: "blue",
 *         label: "Water"
 *     }
 *     
 *     const factory = useFactory(() => [
 *        [dep1, choice1],
 *        [dep2, choice2],
 *        [dep3, choice3]
 *     ], [dep1, dep2, dep3]);
 * 
 *     // Assuming dep1 = false, dep2 = true and dep3 = false:
 *     factory === choice2 // true
 */
export default function useFactory(tuplesFn, deps) {
  const tuples = useMemo(tuplesFn, deps);

  // "testConditionFn" is pure and does never change.
  const testConditionFn = useCallback(
    testCondition =>
      Boolean(
        typeof testCondition === "function" ? testCondition() : testCondition
      ),
    []
  );

  const factoryValue = useMemo(() => {
    let i = 0;
    // Loop through all the tuples except the last one (handled after this loop).
    for (; i < tuples.length - 1; i++) {
      const tuple = tuples[i];
      const [testCondition, factoryValue] = tuple;
      if (testConditionFn(testCondition)) {
        // Test condition for factory value is satisfied.
        return factoryValue;
      }
    }
    const lastTuple = tuples[i];
    if (isArray(lastTuple) && lastTuple.length === 2) {
      const [testCondition, factoryValue] = lastTuple;
      if (testConditionFn(testCondition)) {
        // Test condition for last factory value is satisfied.
        return factoryValue;
      }

      // No default and no factory value satisfying a test condition.
      return void 0;
    } else {
      // Default factory value.
      return lastTuple;
    }
  }, [testConditionFn, tuples]);

  return factoryValue;
}

Работает как this (Codesandbox: https://codesandbox.io/s/react-example-8o9ht):

import ReactDOM from "react-dom";
import React, { useMemo } from "react";
import { useFactory } from "react-js-utl/hooks";

const choice1 = {
  color: "red",
  label: "Fire"
};

const choice2 = {
  color: "green",
  label: "Grass"
};

const choice3 = {
  color: "blue",
  label: "Water"
};

function Example({ dep1, dep2, dep3 }) {
  const factoryValue = useFactory(
    () => [[dep1, choice1], [dep2, choice2], [() => dep3, choice3], "default"],

    // How to tell react-hooks/exhaustive-deps that it should warn me
    // that this array of deps is missing `dep1`, `dep2` and `dep3`?
    [] // No warning, but there should be one...
  );

  // Builtin `useMemo` hook works as expected.
  // react-hooks/exhaustive-deps warns me that the deps array is missing `dep1`, `dep2` and `dep3`:
  //
  //     React Hook useMemo has missing dependencies: 'dep1', 'dep2', and 'dep3'.
  //     Either include them or remove the dependency array. (react-hooks/exhaustive-deps)eslint
  //
  const dummyMemoizedValue = useMemo(() => (dep1 ? dep3 : dep2), []);

  return (
    <div>
      {JSON.stringify(factoryValue)} - {JSON.stringify(dummyMemoizedValue)}
    </div>
  );
}

ReactDOM.render(
  <Example dep1={false} dep2={true} dep3={false} />,
  document.getElementById("root")
);

factoryValue - это { color: "green", label:"Grass" }, поскольку dep2 является единственной истинной опорой, а choice2 является объектом, возвращаемым для нее useFactory.

Но в пользовательском хуке useFactory отсутствуют зависимости dep1, dep2 и dep3, которые используются в его обратном вызове и могут изменяться между повторными рендерингами, и, таким образом, этот компонент может отображать устаревшие данные.

Я бы хотел react-hooks/exhaustive-deps предупредить меня об этом, если, конечно, есть способ сделать это.

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...