Предупреждение для "исчерпывающего deps" продолжает запрашивать полный объект "props" вместо того, чтобы разрешать отдельные свойства "props" в качестве зависимостей

Этот вопрос связан с eslint-plugin-react-hooks

Когда я в CodeSanbox использую React Sandbox, я могу использовать отдельные свойства объекта props в качестве зависимостей для ловушки useEffect:

Пример 1:

useEffect(()=>{
  console.log('Running useEffect...');
  console.log(typeof(props.myProp));    // USING ONLY 'myProp' PROPERTY
},[ ]);                                 // EMPTY ARRAY

Пример 1 дает мне следующее предупреждение в среде CodeSandbox:

В React Hook useEffect отсутствует зависимость: "props.myProp". Либо включите его, либо удалите массив зависимостей. (ответные крюки / исчерпывающие) эслинт

И если я добавлю [props.myProp] к массиву предупреждение уходит.

Но в том же примере 1 в моей локальной среде в VSCode я получаю следующее предупреждение:

У React Hook useEffect отсутствует зависимость: "props". Либо включите его, либо удалите массив зависимостей. Тем не менее, "реквизиты" будут меняться при изменении любого реквизита, поэтому предпочтительным решением является деструктурирование объекта "реквизиты" вне вызова useEffect и обращение к этим конкретным реквизитам внутри useEffect.eslint (response-hooks / исчерпывающе-deps).

Это спрашивает меня, что я скучаю по полной props объект. И если я добавлю [props.myProp] к массиву предупреждение не уходит. Хотя код работает как задумано.

Я ожидаю, что я получу то же поведение, что и CodeSandbox в моей локальной среде в VSCode.

Что может случиться? Могу ли я изменить конфигурацию eslint-plugin-react-hooks?

ПАКЕТЫ

DEV:

"eslint": "^5.10.0",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-react-hooks": "^1.6.1",

ОЧЕРЕДНАЯ

"react": "^16.8.6",
"react-dom": "^16.8.6",

.eslintrc.json

{
  "root"  :true,
  "env": {
    "browser": true,
    "commonjs": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:import/errors"
  ],
  "parser":"babel-eslint",
  "parserOptions": {
    "ecmaVersion": 8,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx":true
    }
  },
  "plugins":[
    "react",
    "react-hooks"
  ],
  "rules": {
    "react/prop-types": 0,
    "semi": "error",
    "no-console": 0,
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  },
  "settings": {
    "import/resolver" : {
      "alias" : {
        "map" : [
          ["@components","./src/components"],
          ["@constants","./src/constants"],
          ["@helpers","./src/helpers"]
        ],
        "extensions": [".js"]
      }
    }
  }
}

2 ответа

Ответ на этот вопрос можно найти здесь: https://github.com/facebook/react/issues/16265

Причина, по которой плагин видит это иначе, заключается в том, что, выполняя props.whatever() вы на самом деле проходите props сам как this ценность для whatever. Так что технически это будет устаревший реквизит.

Читая функцию перед вызовом, вы избегаете проблемы.

Хотя в ответе говорится, что деструктуризация - это ответ, есть небольшая оговорка. Деструктуризация или переназначение либо не будет иметь никакого эффекта, кроме разрешения предупреждения (99% случаев), либо нарушит ваш код. Если вы деструктурируете или переназначаете, функция не будет иметьthis, и если это не проблема, тогда предупреждение было бессмысленным. Вот демонстрация надуманного случая, когда все это имеет значение.

function bark() {
  console.log(`${this.name} barked.`);
}

const mac = {
  name: "mac",
  bark
};

const cheese = {
  name: "cheese",
  bark
};

const DogBark = props => {
  useEffect(() => props.dog.bark(), [props.dog.bark]);

  return null;
};

const Dog = () => {
  const [dog, setDog] = React.useState(mac);

  useEffect(() => setDog(cheese), []);

  // will cheese bark?
  return (
    <DogBark dog={dog} />
  );
};

Сыр не лает. Проблема усугубляется, когда вы начинаете использоватьuseCallback:

const DogBarkByCallback = props => {
  const bark = React.useCallback(() => props.dog.bark(), [props.dog.bark]);
  // every dog should bark, and if the definition of 
  // bark changes even though the dog is the same, it should bark again
  useEffect(() => bark(), [props.dog, bark]); 

  return null;
};

В этом случае Mac дважды лает, потому что обратный вызов не меняется. Таким образом, решение состоит в том, чтобы убедиться, что[props.dog] находится в вашем массиве зависимостей, как рекомендует предупреждение, или чтобы знать, что вам не нужно this и деструктурируйте или переназначьте значение, чтобы обойти предупреждение.

Продемонстрировано здесь, в консоли: https://codesandbox.io/s/exhaustive-deps-fn-mrdld

Рассматривали ли вы деструкцию собственности?

const { myProp } = props
useEffect(()=>{
  console.log('Running useEffect...');
  console.log(typeof(myProp));    // USING ONLY 'myProp' PROPERTY
},[myProp]);  

Я понял, что происходит. Это не ошибка (я думаю).

Этот код:

useEffect(()=>{
  function someFunction() {
    props.whatever();                  // CALLING A FUNCTION FROM PROPS
  }
},[ ]);

Результаты в этом предупреждении:

У React Hook useEffect отсутствует зависимость: "props". Либо включите его, либо удалите массив зависимостей. Однако "реквизит" будет меняться при изменении любого реквизита, поэтому предпочтительным решением является деструктурирование объекта "реквизит" вне вызова useEffect и обращение к этим конкретным реквизитам внутри useEffect. (Реагирующие крючки / исчерпывающий-Deps) eslint


И этот код:

useEffect(()=>{
  function someFunction() {
    props.whatever;                          // ACCESSING A PROPERTY FROM PROPS
  }
},[]);

Результаты в этом предупреждении:

У React Hook useEffect отсутствует зависимость: "props.whwhat". Либо включите его, либо удалите массив зависимостей. (Реагирующие крючки / исчерпывающий-Deps) eslint


Я не уверен, почему, но плагин видит это по-другому, когда вы вызываете метод из props или если ваш доступ property из props,

Другие вопросы по тегам