पैरेंट स्टेट चेंज के बाद अपडेट नहीं होने वाला चाइल्ड कंपोनेंट


109

मैं विभिन्न बाल घटकों में डेटा को पॉप्युलेट करने के लिए एक अच्छा एपिवर्पर घटक बनाने का प्रयास कर रहा हूं। मैंने जो कुछ पढ़ा है, उससे यह काम करना चाहिए: https://jsfiddle.net/vinniejames/m1mesp6z/1/

class ApiWrapper extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      response: {
        "title": 'nothing fetched yet'
      }
    };
  }

  componentDidMount() {
    this._makeApiCall(this.props.endpoint);
  }

  _makeApiCall(endpoint) {
    fetch(endpoint).then(function(response) {
      this.setState({
        response: response
      });
    }.bind(this))
  }

  render() {
    return <Child data = {
      this.state.response
    }
    />;
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: props.data
    };
  }

  render() {
    console.log(this.state.data, 'new data');
    return ( < span > {
      this.state.data.title
    } < /span>);
  };
}

var element = < ApiWrapper endpoint = "https://jsonplaceholder.typicode.com/posts/1" / > ;

ReactDOM.render(
  element,
  document.getElementById('container')
);

लेकिन किसी कारण से, ऐसा लगता है कि मूल घटक में परिवर्तन होने पर बाल घटक अपडेट नहीं हो रहा है।

क्या मुझसे कोई चूक हो रही है?

जवाबों:


204

आपके कोड के साथ दो समस्याएँ हैं।

आपके बच्चे के घटक की प्रारंभिक अवस्था प्रॉप्स से निर्धारित होती है।

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

इस SO उत्तर से उद्धरण :

एक घटक के रूप में एक घटक के रूप में intial राज्य को पारित करना propएक विरोधी पैटर्न है क्योंकि getInitialState(हमारे मामले में अवरोधक) विधि को केवल पहली बार घटक प्रतिपादन कहा जाता है। और कभी नहीं। मतलब यह है कि, यदि आप उस घटक को एक अलग मान के रूप में फिर से प्रस्तुत करते हैं prop, तो घटक उसके अनुसार प्रतिक्रिया नहीं करेगा, क्योंकि घटक पहली बार उस अवस्था से रखेगा जो उसे प्रदान किया गया था। यह बहुत त्रुटि वाला है।

इसलिए यदि आप ऐसी स्थिति से बच नहीं सकते हैं तो आदर्श समाधान componentWillReceivePropsनए प्रॉप्स को सुनने के लिए विधि का उपयोग करना है ।

अपने बच्चे के घटक के लिए नीचे दिए गए कोड को जोड़ने से बाल घटक के साथ आपकी समस्या का फिर से समाधान होगा।

componentWillReceiveProps(nextProps) {
  this.setState({ data: nextProps.data });  
}

दूसरा मुद्दा है fetch

_makeApiCall(endpoint) {
  fetch(endpoint)
    .then((response) => response.json())   // ----> you missed this part
    .then((response) => this.setState({ response }));
}

और यहाँ एक काम कर रहे बेला है: https://jsfiddle.net/o8b04mLy/


1
" अगर आप जानते हैं कि आप क्या कर रहे हैं तो प्रॉप्स के आधार पर राज्य को इनिशियलाइज़ करना ठीक है " क्या कोई अन्य डाउनसाइड्स है जो प्रोप के माध्यम से स्टेट सेट कर सकता है, इस तथ्य के साथ कि nextPropबिना री-रेंडर किए ट्रिगर नहीं होगा componentWillReceiveProps(nextProps)?
विन्नी जेम्स

11
जहां तक ​​मुझे पता है, कोई अन्य डाउनसाइड नहीं हैं। लेकिन आपके मामले में हम स्पष्ट रूप से बाल घटक के अंदर एक राज्य होने से बच सकते हैं। माता-पिता सिर्फ प्रॉप्स के रूप में डेटा पास कर सकते हैं, और जब माता-पिता अपनी नई स्थिति के साथ पुन: प्रतिपादन करते हैं, तो बच्चा भी नए प्रॉप्स के साथ फिर से प्रस्तुतिकरण करेगा। वास्तव में बच्चे के अंदर एक अवस्था बनाए रखना यहाँ अनावश्यक है। शुद्ध घटक FTW!
यदु किरन

7
अब से पढ़ने वाले किसी व्यक्ति के लिए, static getDerivedStateFromProps(nextProps, prevState) reactjs.org/docs/…
GoatsWearHats

4
क्या इसका कोई अन्य हल है जोकि CompWillReceiveProps () के अलावा अन्य है क्योंकि यह अभी घटा है?
लर्निंग

3
@LearningMath कृपया नवीनतम रिएक्ट डॉक्स देखें, जो वैकल्पिक तरीकों के बारे में बोलते हैं। आपको अपने तर्क पर पुनर्विचार करना पड़ सकता है।
यदु किरन

1

कुछ चीजें हैं जिन्हें आपको बदलने की आवश्यकता है।

जब fetchप्रतिक्रिया मिलती है, तो यह एक मजाक नहीं है। मैं इस बात की तलाश कर रहा था कि मुझे यह कैसे मिल सकता है और मैंने इस लिंक को खोज लिया है ।

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

तो, आपको उस तरीके को बदलने की आवश्यकता है जिसे आप <Child>घटक में डेटा पुनर्प्राप्त करते हैं।

यहाँ, मैंने एक उदाहरण कोड छोड़ा: https://jsfiddle.net/emq1ztqj/

मुझे आशा है कि वह मदद करेंगे।


धन्यवाद। हालाँकि, आपने जो उदाहरण दिया है, उसे देखते हुए ऐसा लगता है कि जैसे बाल कभी अपडेट नहीं हुए। बाल डेटा प्राप्त करने के तरीके को बदलने के बारे में कोई सुझाव?
विन्नी जेम्स

2
क्या आपको यकीन है? मुझे लगता है कि <Child>घटक नए डेटा को https://jsonplaceholder.typicode.com/posts/1फिर से प्रस्तुत करता है और पुनः प्राप्त करता है ।
स्लोरेंजो

1
हां, मैं देख रहा हूं कि यह अब OSX पर काम कर रहा है। iOS StackExchange ऐप ब्राउज़र में फिर से रेंडर को ट्रिगर कर रहा था
विन्नी जेम्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.