प्रतिक्रिया: जब परिवर्तन होता है तो चाइल्ड कंपोनेंट अपडेट क्यों नहीं होता है


135

निम्नलिखित छद्म-कोड उदाहरण में क्यों बाल कंटेनर को foo.bar में बदलने पर फिर से प्रस्तुत नहीं करता है?

Container {
  handleEvent() {
    this.props.foo.bar = 123
  },

  render() {
    return <Child bar={this.props.foo.bar} />
}

Child {
  render() {
    return <div>{this.props.bar}</div>
  }
}

भले ही मैं forceUpdate()कंटेनर में मूल्य को संशोधित करने के बाद कॉल करता हूं , फिर भी बाल पुराने मूल्य को दर्शाता है।


5
क्या यह आपका कोड है? ऐसा लगता है कि यह एक मान्य प्रतिक्रिया कोड नहीं है

मुझे लगता है कि प्रॉपर वैल्यू को कन्टेनर कंपोनेंट में नहीं बदलना चाहिए, इसके बजाय सेटस्ट्रेट द्वारा पैरेंट कंपोनेंट में बदलाव करना चाहिए और उस स्टेट को कंटेनर प्रॉप्स में मैप करना चाहिए
पीयूष पटेल

स्प्रेड ऑपरेटर का उपयोग इस तरह से करें <चाइल्ड बार = {... this.props.foo.bar} />
सौरव सिंह

@ AdrianWydmanski और अन्य 5 लोग जिन्होंने उत्थान किया: en.wikipedia.org/wiki/Pseudocode
डेविड न्यूकॉम्ब

@PiyushPatel प्रॉप्स को तब अपडेट किया जाता है जब कोई घटक छद्म कोड शो के उदाहरण के रूप में फिर से प्रदान किया जाता है। इसका एक और उदाहरण उपयोग करने जैसा कुछ है <Route exact path="/user/:email" component={ListUserMessagePage} />, एक ही पृष्ठ पर एक लिंक एक नया उदाहरण बनाए बिना और सामान्य जीवन चक्र की घटनाओं को चलाने के बिना प्रॉप्स को अपडेट करेगा।
डेविड न्यूकॉम्ब

जवाबों:


94

नाम के बराबर विशेषता 'कुंजी' के लिए बच्चे को अपडेट करें। हर बार महत्वपूर्ण परिवर्तन के बाद घटक फिर से प्रस्तुत करेगा।

Child {
  render() {
    return <div key={this.props.bar}>{this.props.bar}</div>
  }
}

5
इसके लिए धन्यवाद। मैं Redux स्टोर का उपयोग कर रहा था और जब तक मैंने एक कुंजी नहीं जोड़ी तब तक अपने घटक को फिर से प्रस्तुत करने के लिए नहीं मिला। (मैंने यादृच्छिक कुंजी उत्पन्न करने के लिए uuid लाइब्रेरी का उपयोग किया, और यह काम किया)।
मैया

हुक का उपयोग करते हुए मेरे बच्चे को मौजूदा सरणी पर राज्य सेट करते समय फिर से प्रस्तुत नहीं किया जाएगा। मेरे (शायद बुरा विचार) हैक एक साथ एक डमी प्रोप के राज्य की स्थापना की और useEffect निर्भरता सरणी है कि जोड़ने के लिए किया गया था: [props.notRenderingArr, props.dummy]। यदि सरणी की लंबाई हमेशा बदलती रहती है, तो आप उपयोग निर्भरता सरणी को सेट कर सकते हैं [props.notRenderingArr.length]
हिप्नोसिस

5
मुझे भी यही चाहिए था। मैं हैरान हूँ, जब एक keyआवश्यकता है, बनाम बस setState? मेरे पास कुछ बच्चे हैं जो माता-पिता की स्थिति पर भरोसा करते हैं लेकिन वे फिर से रेंडर नहीं कर रहे हैं ...
dcsan

बहुत बढ़िया जवाब। लेकिन यह व्यवहार क्यों?
रिशव

1
मैं एक कुंजी के रूप में सूचकांक का उपयोग कर रहा था लेकिन यह ठीक से काम नहीं कर रहा था। अब मैं uuid का उपयोग कर रहा हूं और यह एकदम सही है :) Thanks to @Maiya
Ali Rehman

90

क्योंकि माता-पिता के रंगमंच की सामग्री में बदलाव होने पर बच्चे रेंडर नहीं करते हैं, लेकिन अगर उसका STATE बदल जाए तो :)

आप जो दिखा रहे हैं वह यह है: https://facebook.github.io/react/tips/communicate-between-comports.html

यह प्रॉपर के माध्यम से माता-पिता से बच्चे तक डेटा पास करेगा लेकिन वहां कोई रेंडरर तर्क नहीं है।

आपको माता-पिता के लिए कुछ राज्य सेट करने की आवश्यकता है, फिर बच्चे को माता-पिता के परिवर्तन की स्थिति पर रेंडर करें। यह मदद कर सकता है। https://facebook.github.io/react/tips/expose-component-functions.html


5
ऐसा क्यों है कि setState पुन: प्रस्तुत करने का कारण बनेगा, लेकिन बल नहीं? इसके अलावा थोड़ा बंद विषय, लेकिन कैसे घटकों को अपडेट किया जाता है जब प्रॉप्स को रिडक्स से पारित किया जाता है और यह राज्य कार्रवाई के माध्यम से अपडेट किया जाता है?
तूओमास टिवोनेन

यदि आप उस घटक को अपडेट करते हैं जो आप पास हैं, तब भी प्रॉप्स अपडेट नहीं किए जाते हैं। फ्लक्स एक और विषय है हाँ :)
फ्रांस्वा रिचर्ड

3
राज्य! = आप के बारे में और अधिक पढ़ने की जरूरत है। आप प्रॉप्स के साथ अपडेट नहीं करते हैं
फ्रेंकोइस रिचर्ड

आप इसे सीधे सोर्स कोड में देख सकते हैं, यह बस एक ही प्रक्रिया नहीं है
Webwoman

इसलिए आपने जो यहां कहा है, वह या तो बदल दिया गया है या मैं इसे सही ढंग से नहीं समझ पाया हूं, मैंने इसके लिए एक सवाल किया है, जिस तरह से stackoverflow.com/questions/58903921/…
ILoveReactAndNode

50

मुझे भी यही समस्या थी। यह मेरा समाधान है, मुझे यकीन नहीं है कि अच्छा अभ्यास है, मुझे बताएं यदि नहीं:

state = {
  value: this.props.value
};

componentDidUpdate(prevProps) {
  if(prevProps.value !== this.props.value) {
    this.setState({value: this.props.value});
  }
}

यूपीडी: अब आप रिएक्ट हुक का उपयोग करके एक ही काम कर सकते हैं: (केवल अगर घटक एक फ़ंक्शन है)

const [value, setValue] = useState(propName);
// This will launch only if propName value has chaged.
useEffect(() => { setValue(propName) }, [propName]);

3
यह निश्चित रूप से सही उत्तर है, सरलतम का उल्लेख नहीं करना है
गुइलहर्मे फेरेरा

1
मैं भी इस दृष्टिकोण का उपयोग कर रहा हूं।
रॉल्स

@ वैन्सी-पैंट componentDidUpdateइस मामले में बाल घटक में जाता है।
निक फ्रिस्केल

4
आपको ज़रूरत नहीं है और एक बच्चे के घटक में प्रॉप्स को राज्य में बदलना नहीं चाहिए। बस सीधे प्रॉप्स का उपयोग करें। में FunctionComponentsयह स्वचालित रूप से बच्चे के घटकों अगर रंगमंच की सामग्री परिवर्तन अद्यतन करेगा।
oemera

1
यह दृष्टिकोण तब भी काम करता है जब आपके पास मूल राज्य से प्राप्त बाल घटकों में रंगमंच की सामग्री होती है
Chefk5

10

प्रतिक्रिया के अनुसार दर्शन घटक अपने रंगमंच की सामग्री को नहीं बदल सकता है। उन्हें माता-पिता से प्राप्त किया जाना चाहिए और अपरिवर्तनीय होना चाहिए। केवल माता-पिता ही अपने बच्चों के रंगमंच की सामग्री को बदल सकते हैं।

राज्य बनाम सहारा पर अच्छी व्याख्या

यह भी पढ़ें, मैं प्रतिक्रिया में प्रॉप्स अपडेट क्यों नहीं कर सकता।


क्या इसका मतलब यह भी नहीं है कि कंटेनर रेडक्स स्टोर से प्राप्त होने वाले प्रॉप्स को संशोधित नहीं कर सकता है?
तुओमास तोइवोनेन

3
कंटेनर को सीधे स्टोर से प्रॉप्स प्राप्त नहीं होता है, उन्हें एक रिडक्स स्टेट ट्री (कन्फेडरी ??) के एक हिस्से को पढ़कर आपूर्ति की जाती है। !! भ्रम इसलिए है क्योंकि हम प्रतिक्रिया-रिडक्स द्वारा जादुई फ़ंक्शन कनेक्ट के बारे में नहीं जानते हैं। यदि आप कनेक्ट विधि के स्रोत कोड को देखते हैं, तो मूल रूप से यह एक उच्च क्रम घटक बनाता है, जिसमें संपत्ति भंडार के साथ एक राज्य होता है और इसे रिड्यूक्स स्टोर की सदस्यता दी जाती है। के रूप में storeState पूरे पुन: रेंडरिंग में परिवर्तन करता है, और संशोधित प्रॉप्स को परिवर्तित स्थिति को पढ़कर कंटेनर को आपूर्ति की जाती है। उम्मीद है कि इस प्रश्न का उत्तर दिया जाएगा
सुजान ठाकरे १४'१६ को

उच्च श्रेणी के घटक के बारे में अच्छी व्याख्या, मुझे यह समझने में मदद करती है कि क्या हो रहा है
Tuomas Toivonen

7

आपको setStateफ़ंक्शन का उपयोग करना चाहिए । यदि नहीं, तो राज्य आपके परिवर्तन को नहीं बचाएगा, चाहे आप बल प्रयोग कैसे करें।

Container {
    handleEvent= () => { // use arrow function
        //this.props.foo.bar = 123
        //You should use setState to set value like this:
        this.setState({foo: {bar: 123}});
    };

    render() {
        return <Child bar={this.state.foo.bar} />
    }
    Child {
        render() {
            return <div>{this.props.bar}</div>
        }
    }
}

आपका कोड मान्य नहीं है। मैं इस कोड का परीक्षण नहीं कर सकता।


यह नहीं होना चाहिए <Child bar={this.state.foo.bar} />?
जोश ब्रॉडहर्स्ट

सही। मैं जवाब को अपडेट करता हूं। लेकिन जैसा कि मैंने कहा कि यह एक वैध कोड नहीं हो सकता है। बस प्रश्न से कॉपी करें।
जेम्सयिन

5

जब से रिएक्ट घटक बनाएं functionsऔर useState

const [drawerState, setDrawerState] = useState(false);

const toggleDrawer = () => {
      // attempting to trigger re-render
      setDrawerState(!drawerState);
};

यह काम नहीं करता है

         <Drawer
            drawerState={drawerState}
            toggleDrawer={toggleDrawer}
         />

यह काम करता है (कुंजी जोड़कर)

         <Drawer
            drawerState={drawerState}
            key={drawerState}
            toggleDrawer={toggleDrawer}
         />

3

मुख्य कार्य जोड़कर पुष्टि की गई। मैं डॉक्स के माध्यम से कोशिश करने और समझने के लिए क्यों गया।

बाल घटक बनाते समय प्रतिक्रिया कुशल होना चाहती है। यदि यह दूसरे बच्चे की तरह ही है, तो यह एक नए घटक को प्रस्तुत नहीं करेगा, जिससे पेज लोड तेजी से होता है।

एक नए घटक को रेंडर करने के लिए एक प्रमुख बलों को जोड़ना, इस प्रकार उस नए घटक के लिए राज्य को रीसेट करना।

https://reactjs.org/docs/reconciliation.html#recursing-on-children


2

SetState फ़ंक्शन का उपयोग करें। तो आप कर सकते हैं

       this.setState({this.state.foo.bar:123}) 

हैंडल इवेंट विधि के अंदर।

एक बार, राज्य अद्यतन किया जाता है, यह परिवर्तनों को ट्रिगर करेगा, और फिर से रेंडर करेगा।


1
यह यह होना चाहिए। स्ट्रेटस्टेट ({foo.bar:123}) सही है?
चरिथ जयसंका

0

आपको संभवतः बच्चे को कार्यात्मक घटक बनाना चाहिए, अगर यह किसी भी राज्य को बनाए नहीं रखता है और बस सहारा को बढ़ाता है और फिर इसे माता-पिता से कहता है। इसके लिए वैकल्पिक यह है कि आप कार्यात्मक घटक (यूज़स्टेट) के साथ हुक का उपयोग कर सकते हैं, जो फिर से रेंडर करने के लिए स्टेटलेस घटक का कारण होगा।

इसके अलावा, आपको प्रचार को बदलना नहीं चाहिए क्योंकि वे अपरिवर्तनीय हैं। घटक की स्थिति बनाए रखें।

Child = ({bar}) => (bar);

0

मैं उसी समस्या का सामना कर रहा था। मेरे पास एक Tooltipघटक था जो showTooltipप्रोप प्राप्त कर रहा था, कि मैं Parentएक ifशर्त के आधार पर घटक को अपडेट कर रहा था , यह Parentघटक में अपडेट हो रहा था लेकिन Tooltipघटक प्रतिपादन नहीं कर रहा था।

const Parent = () => {
   let showTooltip = false;
   if(....){ showTooltip = true; }
   return(
      <Tooltip showTooltip={showTooltip}></Tooltip>
   )
}

मैं जो गलती कर रहा था, showTooltipउसे एक घोषणा के रूप में घोषित करना है ।

मुझे एहसास हुआ कि मैं क्या गलत कर रहा था मैं सिद्धांतों का उल्लंघन कर रहा था कि कैसे काम करता है, हुक के साथ इसे काम किया।

const [showTooltip, setShowTooltip] =  React.useState<boolean>(false);

0

बच्चे के घटक में कनेक्ट विधि के mapStateToProps में परिवर्तित प्रॉपर परिभाषित करें।

function mapStateToProps(state) {
  return {
    chanelList: state.messaging.chanelList,
  };
}

export default connect(mapStateToProps)(ChannelItem);

मेरे मामले में, ChannelList का चैनल अपडेट किया गया है, इसलिए मैंने mapStateToProps में chanelList जोड़ा है

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