Предупреждение для "исчерпывающего 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
,