Как исправить предупреждение об отсутствующей зависимости при использовании useEffect React Hook?
С React 16.8.6 (это было хорошо в предыдущей версии 16.8.3), я получаю эту ошибку, когда пытаюсь предотвратить бесконечный цикл при запросе выборки
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
Мне не удалось найти решение, которое останавливает бесконечный цикл. Я хочу держаться подальше от использования useReducer()
. Я нашел это обсуждение https://github.com/facebook/react/issues/14920, где возможное решение - You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.
Я не уверен в том, что я делаю, поэтому я еще не пытался его реализовать.
У меня есть текущая настройка React-хук useEffect работает постоянно навсегда/бесконечный цикл, и единственный комментарий касается useCallback()
, с которым я не знаком.
Как я в настоящее время использую useEffect()
(который я хочу запустить только один раз в начале, аналогично componentDidMount()
)
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
Ответы
Ответ 1
Если вы не используете метод fetchBususiness где-либо кроме эффекта, вы можете просто переместить его в эффект и избежать предупреждения
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
fetchBusinesses();
}, []);
Однако, если вы используете fetchBususiness за пределами рендера, вы должны отметить две вещи
- Если есть какая-либо проблема, если вы не передаете
fetchBusinesses
как метод и что он используется во время монтирования с закрывающим закрытием, проблем не будет. - Зависит ли ваш метод от каких-то переменных, которые он получает из закрытого замыкания, что не так для вас.
- При каждом рендеринге fetchBususiness будет воссоздан, и, следовательно, передача его в useEffect вызовет проблемы. Итак, сначала вы должны запомнить fetchBususiness, если вы должны были передать его в массив зависимостей.
Подводя итог, я бы сказал, что если вы используете fetchBusinesses
за пределами useEffect
вы можете отключить правило, используя //eslint-disable-next-line react-hooks/exhaustive-deps
противном случае вы можете переместить метод внутри useEffect.
Чтобы отключить правило, вы должны написать его так
useEffect(() => {
// other code
...
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Ответ 2
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
Это не ошибка JS/React, а предупреждение eslint (eslint-plugin -act-hooks).
Он говорит вам, что ловушка зависит от функции fetchBusinesses
, поэтому вы должны передать ее как зависимость.
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
Это может привести к вызову функции при каждом отображении, если функция объявлена в компоненте, например:
const Component = () => {
/*...*/
//new function declaration every render
const fetchBusinesses = () => {
fetch('/api/businesses/')
.then(...)
}
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
/*...*/
}
потому что каждый раз функция повторно объявляется с новой ссылкой
Правильный способ сделать это:
const Component = () => {
/*...*/
// keep function reference
const fetchBusinesses = useCallback(() => {
fetch('/api/businesses/')
.then(...)
}, [/* additional dependencies */])
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
/*...*/
}
Подробнее: https://github.com/facebook/react/issues/14920
Ответ 3
Эта статья является хорошим учебником по извлечению данных с помощью хуков: https://www.robinwieruch.de/react-hooks-fetch-data/
По сути, useEffect
определение функции извлечения в useEffect
:
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theUrl"...
// ...your fetch implementation
);
}
fetchBusinesses();
}, []);
Ответ 4
Решение также дается useCallback
, они советуют вам использовать useCallback
который возвратит версию вашей функции в виде useCallback
:
Функция "fetchBususiness" изменяет зависимости useEffect Hook (в строке NN) при каждом рендеринге. Чтобы исправить это, оберните определение 'fetchBususiness' в его собственный useCallback() Hook response-hooks/исчерпывающий-deps
useCallback
прост в использовании, так как имеет ту же сигнатуру, что и useEffect
разница в том, что useCallback возвращает функцию. Это будет выглядеть так:
const fetchBusinesses = useCallback( () => {
return fetch("theURL", {method: "GET"}
)
.then(// some stuff)
.catch(// some error handling)
}, [//deps])
// We have a first effect thant uses fetchBusinesses
useEffect(() => {
// do things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
// We can have many effect thant uses fetchBusinesses
useEffect(() => {
// do other things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
Ответ 5
Вы можете удалить второй тип аргумента array []
но fetchBusinesses()
также будет вызываться при каждом обновлении. Вы можете добавить оператор IF
в реализацию fetchBusinesses()
если хотите.
React.useEffect(() => {
fetchBusinesses();
});
Другой fetchBusinesses()
- реализовать fetchBusinesses()
вне вашего компонента. Только не забудьте передать любые аргументы зависимости в ваш fetchBusinesses(dependency)
, если таковые имеются.
function fetchBusinesses (fetch) {
return fetch("theURL", { method: "GET" })
.then(res => normalizeResponseErrors(res))
.then(res => res.json())
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
}
function YourComponent (props) {
const { fetch } = props;
React.useEffect(() => {
fetchBusinesses(fetch);
}, [fetch]);
// ...
}
Ответ 6
Может быть
useEffect(fetchBusiness,[])
Ответ 7
просто отключите eslint для следующей строки;
useEffect(() => {
fetchBusinesses();
// eslint-disable-next-line
}, [fetchBusinesses]);