W przypadku React 16.8.6 (było dobrze w poprzedniej wersji 16.8.3), pojawia się ten błąd, gdy próbuję zapobiec nieskończonej pętli w żądaniu pobierania
./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
Nie udało mi się znaleźć rozwiązania, które zatrzymałoby nieskończoną pętlę. Chcę trzymać się z daleka od używania useReducer()
. Znalazłem tę dyskusję https://github.com/facebook/react/issues/14920, gdzie możliwym rozwiązaniem jest You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.
brak pewności co do tego, co robię, więc jeszcze nie próbowałem go wdrożyć.
Mam tę bieżącą konfigurację React hook useEffect działa w sposób ciągły w nieskończoność / nieskończoną pętlę, a jedyny komentarz dotyczy tego, z useCallback()
którym nie jestem zaznajomiony.
Jak obecnie używam useEffect()
(które chcę uruchomić tylko raz na początku, podobnie jak 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
});
};
useCallback()
. Na przykład:const fetchBusinesses= useCallback(() => { ... }, [...])
auseEffect()
wyglądałoby to tak:useEffect(() => { fetchBusinesses(); }, [fetchBusinesses]);
// eslint-disable-next-line react-hooks/exhaustive-deps
do wyjaśnienia linterowi, że twój kod jest poprawny, jest jak włamanie. Spodziewam się, że znajdą inne rozwiązanie, które sprawi, że linter będzie wystarczającoTo nie jest błąd JS / React, ale ostrzeżenie eslint (eslint-plugin-aware-hooks).
Mówi ci, że hook zależy od funkcji
fetchBusinesses
, więc powinieneś przekazać to jako zależność.Mogłoby to spowodować wywołanie funkcji przy każdym renderowaniu, jeśli funkcja jest zadeklarowana w komponencie, na przykład:
ponieważ za każdym razem funkcja jest ponownie deklarowana z nowym odniesieniem
Prawidłowy sposób na zrobienie tego to:
lub po prostu definiując funkcję w
useEffect
Więcej: https://github.com/facebook/react/issues/14920
źródło
Line 20: The 'fetchBusinesses' function makes the dependencies of useEffect Hook (at line 51) change on every render. Move it inside the useEffect callback. Alternatively, wrap the 'fetchBusinesses' definition into its own useCallback() Hook
Możesz ustawić go bezpośrednio jako
useEffect
callback:Uruchomi się tylko raz, więc upewnij się, że wszystkie zależności funkcji są poprawnie ustawione (tak samo jak użycie
componentDidMount/componentWillMount...
)Edycja 21.02.2020
Tylko dla kompletności:
1. Użyj funkcji jako
useEffect
wywołania zwrotnego (jak wyżej)2. Zadeklaruj funkcję wewnątrz
useEffect()
3. Zapamiętaj za pomocą
useCallback()
W takim przypadku, jeśli masz zależności w swojej funkcji, będziesz musiał uwzględnić je w
useCallback
tablicy zależności, a to uruchomiuseEffect
ponownie, jeśli parametry funkcji ulegną zmianie. Poza tym jest dużo schematu ... Więc po prostu przekaż funkcję bezpośrednio douseEffect
as in1. useEffect(fetchBusinesses, [])
.4. Wyłącz ostrzeżenie eslint
źródło
Rozwiązaniem jest również reakcja, radzą ci użyć,
useCallback
która zwróci wersję memoize twojej funkcji:useCallback
jest prosty w użyciu, ponieważ ma taką samą sygnaturę, jakuseEffect
różnica polega na tym, że useCallback zwraca funkcję. Wyglądałoby to tak:źródło
Te ostrzeżenia są bardzo pomocne w znajdowaniu komponentów, które nie aktualizują się konsekwentnie: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of- zależności .
Jeśli jednak chcesz usunąć ostrzeżenia z całego projektu, możesz dodać to do swojej konfiguracji eslint:
źródło
Ten artykuł jest dobrym podkładem do pobierania danych za pomocą hooków: https://www.robinwieruch.de/react-hooks-fetch-data/
Zasadniczo dołącz definicję funkcji pobierania do środka
useEffect
:źródło
Możesz usunąć tablicę typu drugiego argumentu,
[]
alefetchBusinesses()
będzie ona również nazywana każdą aktualizacją. Jeśli chcesz, możesz dodaćIF
oświadczenie dofetchBusinesses()
implementacji.Drugim jest zaimplementowanie
fetchBusinesses()
funkcji poza komponentem. Po prostu nie zapomnij przekazać wszelkich argumentów zależności do swojegofetchBusinesses(dependency)
wywołania, jeśli takie istnieją.źródło
W rzeczywistości ostrzeżenia są bardzo przydatne, gdy rozwijasz się z hakami. ale w niektórych przypadkach może cię zranić. zwłaszcza gdy nie musisz nasłuchiwać zmian zależności.
Jeśli nie chcesz wstawiać
fetchBusinesses
wewnątrz zależności podpięcia, możesz po prostu przekazać to jako argument do wywołania zwrotnego hooka i ustawić mainfetchBusinesses
jako wartość domyślną w ten sposóbNie jest to najlepsza praktyka, ale w niektórych przypadkach może być przydatna.
Jak napisał Shubnam, możesz dodać poniższy kod, aby powiedzieć ESLint, aby zignorował sprawdzanie twojego hooka.
źródło
Możesz
fetchBusinesses
całkowicie wyciągnąć ze swojego komponentu:Zapewni to nie tylko proste rozwiązanie i rozwiąże ostrzeżenie wyczerpujące.
fetchBusiness
teraz można go lepiej przetestować i łatwiejComp
, ponieważ znajduje się w zakresie modułu poza drzewem React.Przeniesienie na
fetchBusinesses
zewnątrz działa tutaj dobrze, ponieważ i tak bylibyśmy w stanie odczytać tylko początkowe właściwości i stan z komponentu z powodu nieaktualnego zakresu zamknięcia ([]
dep inuseEffect
).Jak pominąć zależności funkcji
useEffect
zależeć od tej wartości (czysta funkcja obliczeniowa)useCallback
w ostatecznościW przypadku innych rozwiązań:
Wciągnięcie do
fetchBusinesses
środkauseEffect()
nie pomaga, jeśli uzyskasz dostęp do innego stanu w nim. eslint nadal narzekałby: Codesandbox .Chciałbym też powstrzymać się od eslint wyczerpującego-deps ignorować komentarze. Po prostu łatwo o nich zapomnieć, dokonując refaktoryzacji i przeglądu swoich zależności.
źródło
To rozwiązanie jest dość proste i nie ma potrzeby zastępowania ostrzeżeń es-lint. Po prostu utrzymuj flagę, aby sprawdzić, czy komponent jest zamontowany, czy nie.
źródło
spróbuj w ten sposób
i
to dla ciebie praca. Ale moja sugestia jest taka, aby spróbować w ten sposób również dla Ciebie. Jest lepiej niż wcześniej. Używam w ten sposób:
jeśli otrzymujesz dane na podstawie określonego identyfikatora, dodaj wywołanie zwrotne useEffect,
[id]
a następnie nie możesz pokazać ostrzeżeniaReact Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array
źródło
po prostu wyłącz eslint dla następnej linii;
w ten sposób używasz go tak, jak komponent został zamontowany (wywołany raz)
zaktualizowany
lub
fetchBusinesses będzie wywoływane za każdym razem, gdy SomeDeps ulegnie zmianie
źródło
[fetchBusinesses]
zrobię to: automatycznie usunie ostrzeżenie i to rozwiązało problem.useEffect
która sprawdza, czy stan jest pusty.