यूज़फैक्ट रिएक्ट हुक का उपयोग करते समय लापता निर्भरता चेतावनी को कैसे ठीक करें?


179

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.मुझे विश्वास नहीं है कि मैं क्या कर रहा हूं इसलिए मैंने इसे अभी तक लागू करने की कोशिश नहीं की है।

मेरे पास यह वर्तमान सेटअप है रिएक्ट हुक का उपयोग हमेशा के लिए / अनंत लूप लगातार चलता रहता है और एकमात्र टिप्पणी है 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
      });
  };

जवाबों:


192

यदि आप प्रभाव के अलावा कहीं भी fetchBusinesses विधि का उपयोग नहीं कर रहे हैं, तो आप बस इसे प्रभाव में ले जा सकते हैं और चेतावनी से बच सकते हैं

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();
}, []);

यदि आप रेंडर के बाहर fetchBusinesses का उपयोग कर रहे हैं, तो आपको दो चीजों पर ध्यान देना चाहिए

  1. क्या आपके पास कोई ऐसा तरीका नहीं है जब आप इसे बंद करने के दौरान माउंट के दौरान इस्तेमाल करने की विधि के रूप में पारित नहीं कर रहे हैंfetchBusinesses ?
  2. क्या आपका तरीका कुछ चरों पर निर्भर करता है, जो इसे अपने घेरने के बंद होने से प्राप्त होता है? यह आपके लिए मामला नहीं है।
  3. हर रेंडर पर, fetchBusinesses फिर से बनाया जाएगा और इसलिए इसे उपयोग करने के लिए पास करने से समस्याएँ पैदा होंगी। यदि आप इसे निर्भरता सरणी में पारित करने के लिए थे, तो पहले आपको fetchBusinesses को याद करना होगा।

इसे सम्‍मिलित करने के लिए मैं कहूंगा कि यदि आप fetchBusinessesबाहर का उपयोग कर रहे useEffectहैं तो नियम का उपयोग करके इसे निष्क्रिय कर सकते हैं // eslint-disable-next-line react-hooks/exhaustive-depsअन्यथा आप उपयोग विधि के अंदर विधि को स्थानांतरित कर सकते हैं

नियम को निष्क्रिय करने के लिए आप इसे लिखेंगे

useEffect(() => {
   // other code
   ...

   // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) 

14
मैंने आपके द्वारा बताए गए समाधान का अच्छी तरह से उपयोग किया। एक और समाधान है कि मैं एक और जहां एक अलग सेटअप की वजह से इस्तेमाल किया गया था useCallback()। इसलिए उदाहरण के लिए: const fetchBusinesses= useCallback(() => { ... }, [...]) और useEffect()इस तरह दिखेगा:useEffect(() => { fetchBusinesses(); }, [fetchBusinesses]);
russ

1
@ सही, आप सही हैं, आपको भ्रू का उपयोग करने की आवश्यकता होगी। यदि आप इसे निर्भरता सरणी में पास करने के लिए उपयोग कर रहे हैं, तो
शुभम खत्री

यह अच्छा होगा यदि आप दिखाते हैं कि एस्लिंट-डिसेबल स्टेटमेंट कहां रखा गया है। मैंने सोचा कि यह उपयोग से ऊपर होगा
user210757

1
// eslint-disable-next-line react-hooks/exhaustive-depsलिंटर को समझाने के लिए उपयोग करना कि आपका कोड सही है, हैक की तरह है। मुझे उम्मीद है कि वे तर्क को अनिवार्य नहीं करने के लिए लिंटर को और अधिक चालाक बनाने के लिए एक और समाधान पाएंगे
ओलिवियर बोइस

1
@TapasAdhikary, हां आप का उपयोग में एक async फ़ंक्शन हो सकता है, आपको बस इसे अलग तरह से लिखने की आवश्यकता है। कृपया stackoverflow.com/questions/53332321/…
शुभम खत्री

75
./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

यह जेएस / रिएक्ट त्रुटि नहीं है, लेकिन एस्लिंट (एस्लिंट-प्लगइन-रिएक्शन-हुक) चेतावनी है।

यह आपको बता रहा है कि हुक कार्य पर निर्भर करता है 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]);

  /*...*/
}

या सिर्फ परिभाषित समारोह में useEffect

अधिक: https://github.com/facebook/react/issues/14920


14
इसके परिणामस्वरूप एक नई त्रुटि है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
रुस

1
समाधान ठीक है और यदि फ़ंक्शन पर आप किसी अन्य राज्य को संशोधित करते हैं तो आपको एक और अप्रत्याशित व्यवहार से बचने के लिए निर्भरता को जोड़ना होगा
cesarlarsson

57

आप इसे सीधे useEffectकॉलबैक के रूप में सेट कर सकते हैं :

useEffect(fetchBusinesses, [])

यह केवल एक बार ट्रिगर होगा, इसलिए सुनिश्चित करें कि सभी फ़ंक्शन की निर्भरता सही ढंग से सेट की गई है (उपयोग के रूप में componentDidMount/componentWillMount...)


संपादित करें 02/21/2020

पूर्णता के लिए:

1. useEffectकॉलबैक के रूप में फ़ंक्शन का उपयोग करें (ऊपर के रूप में)

useEffect(fetchBusinesses, [])

2. अंदर फंक्शन को डिक्लेयर करें useEffect()

useEffect(() => {
  function fetchBusinesses() {
    ...
  }
  fetchBusinesses()
}, [])

3. के साथ याद useCallback()

इस स्थिति में, यदि आपके फ़ंक्शन में निर्भरताएं हैं, तो आपको उन्हें useCallbackनिर्भरता सरणी में शामिल करना होगा और useEffectफ़ंक्शन के पार्म्स को बदलने पर यह फिर से चालू हो जाएगा । इसके अलावा, यह बॉयलरप्लेट का एक बहुत कुछ है ... तो बस के useEffectरूप में सीधे समारोह में पास 1. useEffect(fetchBusinesses, [])

const fetchBusinesses = useCallback(() => {
  ...
}, [])
useEffect(() => {
  fetchBusinesses()
}, [fetchBusinesses])

4. एस्लेंट की चेतावनी को अक्षम करें

useEffect(() => {
  fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

2
आई लव यू… ये जवाब तो पूरा है!
Nick09

8

समाधान भी प्रतिक्रिया द्वारा दिया जाता है, वे आपको सलाह देते हैं useCallbackकि आप अपने फ़ंक्शन का एक यादगार संस्करण लौटाएंगे:

'FetchBusinesses' फंक्शन हर रेंडर पर यूज़फेक्ट हुक (लाइन एनएन) में बदलाव की निर्भरता बनाता है। इसे ठीक करने के लिए, 'fetchBusinesses' परिभाषा को अपने स्वयं के उपयोग में लपेटें (वापस) हुक प्रतिक्रिया-हुक / संपूर्ण- deps

useCallbackयह उपयोग करने के लिए सरल है क्योंकि इसमें एक ही हस्ताक्षर है क्योंकि useEffectअंतर यह है कि उपयोग कॉलबैक एक फ़ंक्शन देता है। यह इस तरह दिखेगा:

 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]);

2

ये चेतावनी उन घटकों को खोजने के लिए बहुत सहायक है जो लगातार अद्यतन नहीं करते हैं: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of/ निर्भरता

हालाँकि, यदि आप अपने पूरे प्रोजेक्ट के दौरान चेतावनियाँ निकालना चाहते हैं, तो आप इसे अपने अनुलग्‍नक कॉन्फ़िगरेशन में जोड़ सकते हैं:

  {
  "plugins": ["react-hooks"],
  "rules": {
    "react-hooks/exhaustive-deps": 0
    }
  }

1

यह लेख हुक के साथ डेटा लाने के लिए एक अच्छा प्राइमर है: https://www.robinwieruch.de/react-hooks-fetch-data/

अनिवार्य रूप से, अंदर भ्रूण फ़ंक्शन परिभाषा शामिल करें useEffect:

useEffect(() => {
  const fetchBusinesses = () => {
    return fetch("theUrl"...
      // ...your fetch implementation
    );
  }

  fetchBusinesses();
}, []);

1

आप 2 तर्क प्रकार सरणी को निकाल सकते हैं, []लेकिन fetchBusinesses()इसे भी हर अपडेट कहा जाएगा। आप चाहें तो कार्यान्वयन IFमें एक बयान जोड़ सकते हैं fetchBusinesses()

React.useEffect(() => {
  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]);

  // ...
}

0

वास्तव में चेतावनी तब बहुत उपयोगी होती है जब आप हुक के साथ विकसित होते हैं। लेकिन कुछ मामलों में, यह आपको सुई लगा सकता है। खासकर जब आपको निर्भरता बदलने के लिए सुनने की आवश्यकता नहीं है।

यदि आप fetchBusinessesहुक की निर्भरता के अंदर नहीं डालना चाहते हैं , तो आप इसे हुक के कॉलबैक में एक तर्क के रूप में पास कर सकते हैं और मुख्य fetchBusinessesको इसके लिए डिफ़ॉल्ट मान के रूप में सेट कर सकते हैं।

useEffect((fetchBusinesses = fetchBusinesses) => {
   fetchBusinesses();
}, []);

यह सबसे अच्छा अभ्यास नहीं है लेकिन यह कुछ मामलों में उपयोगी हो सकता है।

जैसा कि शुभनाम ने लिखा है, आप अपने हुक की जाँच को अनदेखा करने के लिए ESLint को बताने के लिए नीचे दिए गए कोड को जोड़ सकते हैं।

// eslint-disable-next-line react-hooks/exhaustive-deps

0

मैं केवल [चलाना चाहते हैं fetchBusinesses] एक बार शुरुआत समान करने के लिएcomponentDidMount()

आप fetchBusinessesअपने घटक से पूरी तरह से बाहर निकाल सकते हैं:

const fetchBusinesses = () => { // or pass some additional input from component as args
  return fetch("theURL", { method: "GET" }).then(n => process(n));
};

const Comp = () => {
  React.useEffect(() => {
    fetchBusinesses().then(someVal => {
      // ... do something with someVal
    });
  }, []); // eslint warning solved!
  return <div>{state}</div>;
};

यह न केवल एक सरल समाधान प्रदान करेगा और थकावट-डिप्स चेतावनी को हल करेगा। fetchBusinessअब इसे बेहतर तरीके से जांचा जा सकता है और Compइसमें आसानी होती है, क्योंकि यह रिएक्ट ट्री के बाहर मॉड्यूल के दायरे में रहता है।

स्थानांतरित करने fetchBusinessesके बाहर काम करता है अच्छी तरह से यहाँ, हम केवल पढ़ने के लिए सक्षम हो जाएगा के रूप में प्रारंभिक बासी बंद गुंजाइश (के कारण घटक वैसे भी से रंगमंच की सामग्री और राज्य []में डीईपी useEffect)।

फ़ंक्शन निर्भरता को कैसे छोड़ें

  • प्रभाव के अंदर समारोह ले जाएँ
  • घटक के बाहर फ़ंक्शन ले जाएं - (हम इसका उपयोग कर रहे हैं)
  • रेंडरिंग के दौरान फ़ंक्शन को कॉल करें और useEffectइस मान पर निर्भर करें (शुद्ध गणना फ़ंक्शन)
  • डिप्स को प्रभावी करने के लिए फ़ंक्शन को जोड़ें और इसे useCallbackअंतिम उपाय के रूप में लपेटें

अन्य समाधानों के बारे में:

fetchBusinessesअंदर खींचने से useEffect()वास्तव में मदद नहीं मिलती है, अगर आप इसमें अन्य राज्य का उपयोग करते हैं। एस्क्लिंट को फिर भी शिकायत होगी: कोड्सबॉक्स

मैं भी एग्जिल्ट एग्जॉस्ट-डिप्स से कमेंट्स को अनदेखा करता रहूंगा। जब आप कुछ निर्भरता और अपने आश्रितों के उपहास करते हैं तो उन्हें भूलना आसान होता है।


0
const [mount, setMount] = useState(false)
const fetchBusinesses = () => { 
   //function defination
}
useEffect(() => {
   if(!mount) {
      setMount(true);
      fetchBusinesses();
   }
},[fetchBusinesses]);

यह समाधान बहुत सरल है और आपको es-lint चेतावनियों को ओवरराइड करने की आवश्यकता नहीं है। घटक को माउंट किया गया है या नहीं यह जांचने के लिए बस एक ध्वज बनाए रखें।


0

तुम इस तरह से कोशिश करो

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
      });
  };

तथा

useEffect(() => {
    fetchBusinesses();
  });

यह आपके लिए काम कर रहा है। लेकिन मेरा सुझाव है कि इस तरह से भी आप के लिए काम करने की कोशिश है। यह पहले से बेहतर है। मैं इस तरह से उपयोग करता हूं:

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();
      }, []);

यदि आपको विशिष्ट आईडी के आधार पर डेटा मिलता है, तो कॉलबैक उपयोग में जोड़ें, [id]फिर आपको चेतावनी नहीं दिखा सकता है React Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array


-4

बस अगली पंक्ति के लिए एस्लेंट को अक्षम करें;

useEffect(() => {
   fetchBusinesses();
// eslint-disable-next-line
}, []);

इस तरह से आप इसे एक घटक की तरह माउंट कर रहे हैं (एक बार कहा जाता है)

अद्यतन

या

const fetchBusinesses = useCallback(() => {
 // your logic in here
 }, [someDeps])

useEffect(() => {
   fetchBusinesses();
// no need to skip eslint warning
}, [fetchBusinesses]); 

fetchBusinesses को हर बार कहा जाएगा कुछ डिडैप्स बदल जाएंगे


अक्षम करने के बजाय, बस ऐसा करना: [fetchBusinesses]स्वचालित रूप से चेतावनी को हटा देगा और मेरे लिए समस्या हल हो जाएगी।
रोटिमी-बेस्ट

7
@RotimiBest - ऐसा करने से प्रश्न में वर्णित अनंत पुन: रेंडर हो जाता है
user210757

मैंने वास्तव में कुछ समय पहले अपनी परियोजनाओं में इस तरह से किया था और यह एक अनंत लूप का उत्पादन नहीं करता था। मैं फिर से जाँच करूँगा।
रोटिमी-बेस्ट

@ user210757 प्रतीक्षा करें, लेकिन यह एक अनंत लूप क्यों पैदा करेगा, इसकी तरह आप सर्वर से डेटा प्राप्त करने के बाद राज्य स्थापित नहीं कर रहे हैं। यदि आप राज्य को अपडेट कर रहे थे, तो useEffectयदि राज्य खाली है, तो उस चेक में फ़ंक्शन को कॉल करने से पहले यदि कोई शर्त लिखता है।
रोटिमी-बेस्ट

जब से मैंने टिप्पणी की थी तब से रोटिमी-बेस्ट अह्वेलित है, लेकिन मैं कहूंगा कि फ़ंक्शन हर बार फिर से बनाया जाता है, इसलिए कभी भी ऐसा नहीं होता है, इसलिए जब तक आप यूज़फैक्ट बॉडी या यूज़ कॉलबैक में नहीं जाते हैं, तब तक इसे हमेशा रेंडर नहीं किया जाएगा।
user210757
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.