क्या मैं एक उपयोग हुक के अंदर राज्य सेट कर सकता हूं


123

कहते हैं कि मेरा कुछ राज्य है जो किसी अन्य राज्य पर निर्भर है (उदाहरण के लिए जब A परिवर्तन मैं B को बदलना चाहता हूं)।

क्या एक हुक बनाने के लिए उपयुक्त है जो A का अवलोकन करता है और B का उपयोग करता है।

क्या प्रभाव ऐसे कैस्केड होगा, जब मैं बटन पर क्लिक करता हूं, तो पहला प्रभाव फायर करेगा, जिससे b बदल जाएगा, जिससे दूसरा प्रभाव होगा, अगले रेंडर से पहले? क्या इस तरह के कोड को संरचित करने के लिए कोई प्रदर्शन डाउन है?

let MyComponent = props => {
  let [a, setA] = useState(1)
  let [b, setB] = useState(2)
  useEffect(
    () => {
      if (/*some stuff is true*/) {
        setB(3)
      }
    },
    [a],
  )
  useEffect(
    () => {
      // do some stuff
    },
    [b],
  )

  return (
    <button
      onClick={() => {
        setA(5)
      }}
    >
      click me
    </button>
  )
}

जवाबों:


31

रेंडर चरण पूरा होने के बाद प्रभाव हमेशा निष्पादित होते हैं भले ही आप एक प्रभाव के अंदर सेट करें, एक और प्रभाव अद्यतन स्थिति को पढ़ेगा और रेंडर चरण के बाद ही उस पर कार्रवाई करेगा।

यह कहते हुए कि इसकी दोनों कार्रवाईयों को एक ही प्रभाव में लेना बेहतर है जब तक कि ऐसी कोई संभावना नहीं है कि किन bकारणों के कारण changing aआप एक ही तर्क को अंजाम देना चाहेंगे।


4
तो अगर A परिवर्तन B करता है, तो घटक दो बार सही प्रस्तुत करेगा?
डैन रुसविक

2
मैं ऊपर दिए गए सवाल का जवाब भी जानना चाहता हूं
अलाबौदी

2
@alaboudi हां, यदि A परिवर्तन का उपयोग करने के लिए कारण बनता है जो B को सेट करता है तो घटक दो बार प्रस्तुत करता है
शुभम खत्री

@alaboudi हां .. जैसा कि शुभम खत्री ने कहा कि यह फिर से प्रस्तुत करेगा। लेकिन आप दूसरे आर्ग्यूमेंट का उपयोग करके पुनः प्रभाव डालने के बाद अपना प्रभाव छोड़ना शुरू कर सकते हैं। Reajs.org/docs/…
कार्तिकेयन

107

आम तौर पर बोलना, setStateअंदर useEffectका उपयोग एक अनंत लूप पैदा करेगा जो सबसे अधिक संभावना है कि आप कारण नहीं बनाना चाहते हैं। उस नियम के कुछ अपवाद हैं जो मुझे बाद में मिलेंगे।

useEffectप्रत्येक रेंडर के बाद कहा जाता है और जब setStateइसके अंदर उपयोग किया जाता है, तो यह घटक को फिर से रेंडर करने का कारण बनेगा जो कॉल करेगा useEffectऔर इसी तरह और इतने पर।

लोकप्रिय मामलों में से एक है कि useStateअंदर का उपयोग करने से useEffectएक अनंत लूप का कारण नहीं होगा, जब आप एक खाली सरणी को दूसरे तर्क के रूप में पास करते हैं useEffectजैसे useEffect(() => {....}, [])कि इसका मतलब है कि प्रभाव फ़ंक्शन को एक बार बुलाया जाना चाहिए: केवल पहले माउंट / रेंडर के बाद। यह व्यापक रूप से उपयोग किया जाता है जब आप एक घटक में डेटा ला रहे हैं और आप घटक की स्थिति में अनुरोध डेटा सहेजना चाहते हैं।


3
setStateअंदर उपयोग करने का एक अन्य मामला सदस्यता या ईवेंट श्रोताओं के अंदर useEffectहै setting state। लेकिन सब्सक्राइब करना ना भूलें। reactjs.org/docs/hooks-effect.html#effects-with-cleanup
timqian

35
यह कड़ाई से सच नहीं है - केवल तब उपयोग करें जब आप जिस मूल्य को राज्य के साथ अपडेट कर रहे हैं वह पिछले एक से अलग है इसलिए अनंत लूप को रोका जाता है जब तक कि चक्रों के बीच मूल्य में परिवर्तन न हो।
RobM

14
यह उत्तर गलत है और प्रश्न के बिंदु तक नहीं है: कोड के मामले में, घटक केवल दो बार जब बटन क्लिक किया जाता है, तो कोई अनंत लूप नहीं होता है
बोगदान डी

15
उपयोग के अंदर राज्य को सेट करने के लिए यह एक बहुत ही सामान्य उपयोग मामला है। डेटा लोडिंग के बारे में सोचें, कॉल एपीआई का उपयोग करें, डेटा प्राप्त करता है, उपयोग के सेट भाग का उपयोग करके सेट करता है।
badbod99

3
मैंने आपके द्वारा बताए गए मुद्दों के समाधान के लिए उत्तर को अपडेट किया है, क्या यह अब बेहतर है?
होसम मौराड

58

भविष्य के उद्देश्यों के लिए, यह भी मदद कर सकता है:

यह ठीक है कि useEffectआप में सेटस्टैट का उपयोग करें, बस एक लूप न बनाने के लिए पहले से वर्णित के रूप में ध्यान देने की आवश्यकता है।

लेकिन यह एकमात्र समस्या नहीं है जो हो सकती है। निचे देखो:

कल्पना कीजिए कि आपके पास एक घटक है Compजो propsमाता-पिता से प्राप्त होता है और एक propsपरिवर्तन के अनुसार आप Compराज्य स्थापित करना चाहते हैं । किसी कारण से, आपको प्रत्येक प्रॉप के लिए एक अलग में बदलना होगा useEffect:

यह मत करो

useEffect(() => {
  setState({ ...state, a: props.a });
}, [props.a]);

useEffect(() => {
  setState({ ...state, b: props.b });
}, [props.b]);

यह कभी नहीं बदल सकता है जैसा कि आप इस उदाहरण में देख सकते हैं: https://codesandbox.io/s/confident-lederberg-dtx7w

इस उदाहरण में ऐसा क्यों होता है, इसका कारण यह है कि दोनों उपयोग एक ही प्रतिक्रिया चक्र में चलते हैं जब आप दोनों बदलते हैं prop.aऔर prop.bइसलिए {...state}जब आप करते setStateहैं तो दोनों में समान मूल्य होते हैं useEffectक्योंकि वे एक ही संदर्भ में होते हैं। जब आप दूसरा चलाते हैं तो setStateयह पहले की जगह लेगा setState

इसे स्थापित करें

इस समस्या का हल मूल रूप से setStateइस तरह है:

useEffect(() => {
  setState(state => ({ ...state, a: props.a }));
}, [props.a]);

useEffect(() => {
  setState(state => ({ ...state, b: props.b }));
}, [props.b]);

यहाँ समाधान की जाँच करें: https://codesandbox.io/s/mutable-surf-nynlx

जब आप आगे बढ़ते हैं, तो आप हमेशा राज्य का सबसे अद्यतन और सही मान प्राप्त करते हैं setState

मुझे उम्मीद है इससे किसी को सहायता मिलेगी!


3
उपरोक्त समाधान ने मेरी मदद कीsetName(name => ({ ...name, a: props.a }));
mufaddal_mw

2
इसने मुझे तीर समारोह के साथ भाग में भी मदद कीsetItems(items => [...items, item])
स्टीफन झेल्याज़कोव

वाह, तुम कमाल हो। आपने आज मेरा * s बचा लिया।
प्रतीक सोनी

बिना समाधान के सुबह 7 बजे से दोपहर 3 बजे तक खर्च किया और अब आपने मुझे बचा लिया।
दीनिन्दु कंचना

24

useEffectएक निश्चित प्रोप या राज्य पर हुक कर सकते हैं। इसलिए, अनंत लूप हुक से बचने के लिए आपको जिस चीज की आवश्यकता होती है वह प्रभावी होने के लिए कुछ चर या अवस्था को बांध रही है

उदाहरण के लिए:

useEffect(myeffectCallback, [])

एक बार घटक के प्रदान किए जाने के बाद ही उपरोक्त प्रभाव से आग लग जाएगी। यह componentDidMountजीवनचक्र के समान है

const [something, setSomething] = withState(0)
const [myState, setMyState] = withState(0)
useEffect(() => {
  setSomething(0)
}, myState)

उपर्युक्त प्रभाव से ही मेरे राज्य में आग लगेगी, यह परिवर्तन के समान है componentDidUpdateन कि हर बदलते राज्य में आग लग जाएगी।

आप इस लिंक पर अधिक विवरण पढ़ सकते हैं


1
धन्यवाद, यह उत्तर एक तरह से उपयोग की निर्भरता को संबोधित करता है जिस तरह से अन्य उत्तर नहीं दिया। उपयोग करने के लिए एक दूसरे तर्क के रूप में एक खाली सरणी को शामिल करना सुनिश्चित करें कि घटक का उपयोग करने के बाद एक बार उपयोग निष्पादित हो जाएगा, लेकिन एक विशिष्ट राज्य या विशिष्ट राज्यों के साथ एक सरणी सहित उपयोग के कारण उपयोग को निष्पादित करने का कारण होगा जब संदर्भ में राज्यों को बदल दिया जाता है।
adriaanbd

11

Set 1. क्या मैं एक उपयोग हुक के अंदर राज्य सेट कर सकता हूं?

सिद्धांत रूप में, आप स्वतंत्र रूप से राज्य सेट कर सकते हैं जहां आपको इसकी आवश्यकता होती है - अंदर भीuseEffect और प्रतिपादन के दौरान भी । बस हुक को depsठीक से और / या सशर्त रूप से व्यवस्थित करके अनंत छोरों से बचने के लिए सुनिश्चित करें ।


▶ 2. चलो कहते हैं कि मेरे पास कुछ राज्य है जो किसी अन्य राज्य पर निर्भर है। क्या एक हुक बनाने के लिए उपयुक्त है जो A का अवलोकन करता है और B का उपयोग करता है।

आपने अभी इसके लिए क्लासिक उपयोग के मामले का वर्णन किया हैuseReducer :

useReducerआमतौर पर useStateतब बेहतर होता है जब आपके पास जटिल राज्य तर्क होता है जिसमें कई उप-मान शामिल होते हैं या जब अगला राज्य पिछले एक पर निर्भर करता है। ( प्रतिक्रिया डॉक्स )

जब एक राज्य चर सेट करना दूसरे राज्य चर के वर्तमान मूल्य पर निर्भर करता है , तो आप उन दोनों के साथ प्रतिस्थापित करने का प्रयास करना चाह सकते हैं । [...] जब आप खुद को लिखते हुए पाते हैं , तो इसके बजाय एक reducer का उपयोग करने पर विचार करने का एक अच्छा समय है। ( दान अब्रामोव, ओवररेटेड ब्लॉग )useReducer setSomething(something => ...)


▶ 3. क्या प्रभाव ऐसे कैस्केड होगा, जब मैं बटन पर क्लिक करता हूं, तो पहला प्रभाव फायर करेगा, जिससे b बदल जाएगा, जिससे दूसरा प्रभाव होगा, अगले रेंडर से पहले?

useEffectहमेशा रेंडर होने के बाद रन होता है और DOM में बदलाव होते हैं। पहला प्रभाव आग देता है, बदलता है bऔर फिर से रेंडर करता है। इसके बाद रेंडर पूरा हो गया है, दूसरा प्रभाव bपरिवर्तनों के कारण चलेगा ।


▶ 4. क्या इस तरह के कोड को संरचित करने के लिए कोई प्रदर्शन डाउन है?

हाँ। के राज्य परिवर्तन लपेटकर द्वारा bएक अलग में useEffectके लिए a, ब्राउज़र एक अतिरिक्त लेआउट / रंग चरण है - इन प्रभावों को संभावित रूप से उपयोगकर्ता के लिए दिखाई दे रहे हैं। यदि कोई तरीका नहीं है जिसे आप useReducerआज़माना चाहते हैं , तो आप सीधे bराज्य को एक साथ बदल सकते हैं a:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.