Ana Durum Değişikliğinden Sonra Alt Bileşen Güncellenmeyen React Alt Bileşeni


111

Verileri çeşitli alt bileşenlerde doldurmak için güzel bir ApiWrapper bileşeni yapmaya çalışıyorum. Okuduğum her şeyden, bu işe yaramalı: 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')
);

Ancak bazı nedenlerden dolayı, üst öğe durumu değiştiğinde alt bileşen güncellenmiyor gibi görünüyor.

Burada bir şey mi kaçırıyorum?

Yanıtlar:


207

Kodunuzla ilgili iki sorun var.

Alt bileşeninizin başlangıç ​​durumu, props'tan ayarlanır.

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

Bu SO Cevabından Alıntı :

İlk durumu bir bileşene bir bileşen olarak geçirmek prop bir anti-model bir anti-modeldir, çünkü getInitialState(bizim durumumuzda yapılandırıcı) yöntemi yalnızca bileşen ilk kez işlendiğinde çağrılır. Asla daha fazla. Yani, bu bileşeni a olarak farklı bir değer geçirerek yeniden işlerseniz, bileşen propbuna göre tepki vermeyecektir çünkü bileşen durumu ilk oluşturulduğu andan itibaren koruyacaktır. Hataya çok açık.

Öyleyse, böyle bir durumdan kaçınamazsanız, ideal çözüm yöntemi componentWillReceivePropsyeni sahne donanımı dinlemek için kullanmaktır .

Aşağıdaki kodu alt bileşeninize eklemek, Alt bileşen yeniden oluşturma ile ilgili sorununuzu çözecektir.

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

İkinci konu, fetch .

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

Ve işte çalışan bir keman: https://jsfiddle.net/o8b04mLy/


1
"Ne yaptığınızı biliyorsanız , durumu sahne temelli olarak başlatmakta sorun yok " nextPropolmadan bir yeniden oluşturmayı tetiklemeyecek olmasının yanı sıra, durumu prop aracılığıyla ayarlamanın başka dezavantajları var componentWillReceiveProps(nextProps)mı?
Vinnie James

11
Bildiğim kadarıyla başka dezavantaj yok. Ancak sizin durumunuzda, alt bileşen içinde bir durumdan açıkça kaçınabiliriz. Ebeveyn, verileri yalnızca props olarak aktarabilir ve ebeveyn yeni durumuyla yeniden oluşturduğunda, çocuk da yeniden oluşturur (yeni props ile). Aslında burada çocuğun içinde bir durumu sürdürmek gereksizdir. Saf bileşenler FTW!
Yadhu Kiran

7
Şu andan itibaren okuyan herkes için static getDerivedStateFromProps(nextProps, prevState) reactjs.org/docs/…
adresini

4
Artık kullanımdan kaldırıldığı için componentWillReceiveProps () dışında başka bir çözüm var mı?
LearningMath

3
@LearningMath lütfen alternatif yollardan bahseden en son React belgelerine bakın . Mantığınızı yeniden gözden geçirmeniz gerekebilir.
Yadhu Kiran

1

Değiştirmeniz gereken bazı şeyler var.

Ne zaman fetchyanıt almak, bu bir json değildir. Bu json'u nasıl alabilirim diye bakıyordum ve bu bağlantıyı keşfettim .

Öte yandan, bu constructorişlevin yalnızca bir kez çağrıldığını düşünmeniz gerekir .

Bu nedenle, <Child>bileşendeki verileri alma şeklinizi değiştirmeniz gerekir .

Burada örnek bir kod bıraktım: https://jsfiddle.net/emq1ztqj/

Umarım bu yardımcı olur.


Teşekkür ederim. Yine de yaptığınız örneğe baktığınızda, Çocuk hiç güncelleme yapmamış gibi görünüyor. Çocuğun verileri alma şeklini değiştirme konusunda herhangi bir öneriniz var mı?
Vinnie James

2
Emin misiniz? Bu <Child>bileşenin yeni verileri aldığını https://jsonplaceholder.typicode.com/posts/1ve yeniden oluşturduğunu görüyorum .
slorenzo

1
Evet, şimdi OSX'te çalıştığını görüyorum. iOS, StackExchange uygulama tarayıcısında yeniden oluşturmayı tetiklemiyordu
Vinnie James
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.