Tepki bileşeni, sahne biriminden durumu başlatma


206

React'te bu iki uygulama arasında gerçek farklılıklar var mı? Bazı arkadaşlar bana FirstComponent'in kalıp olduğunu söylüyor, ama nedenini göremiyorum. İkinci bileşen daha basit görünüyor çünkü oluşturma yalnızca bir kez çağrılıyor.

İlk:

import React, { PropTypes } from 'react'

class FirstComponent extends React.Component {

  state = {
    description: ''
  }

  componentDidMount() {
    const { description} = this.props;
    this.setState({ description });
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} /> 
    );
  }
}

export default FirstComponent;

İkinci:

import React, { PropTypes } from 'react'

class SecondComponent extends React.Component {

  state = {
    description: ''
  }

  constructor (props) => {
    const { description } = props;
    this.state = {description};
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} />   
    );
  }
}

export default SecondComponent;

Güncelleme: setState () öğesini this.state = {} olarak değiştirdim (teşekkürler joews), Ancak yine de farkı görmüyorum. Biri diğerinden daha iyi mi?


10
Sahne malzemelerini neden devlette saklıyorsun? Bir değeri önbelleğe almak yerine desteklerinizi doğrudan kullanmalısınız. Bir okuma var React.js Devlet olarak Dikmeler ayarlanması neden küfür olduğunu ve getInitialState içinde Dikmeler bir Anti-Desen mi .
Aurora0001

12
Bir örnek - değiştirilebilir bir bileşen (örneğin bir popover veya çekmece). Ebeveyn, bileşenin açık veya kapalı başlayıp başlamayacağını bilir; bileşenin kendisi, bir noktada açık olup olmadığını bilebilir. Bu durumda bence this.state = { isVisible: props.isVisible }mantıklı. Uygulamanın UI durumunu nasıl dağıttığına bağlıdır.
20'de joews


5
2017'de Facebook, belgelerinde başlangıç ​​durumunu ayarlamak için sahne donanımlarını
Rohmer

1
@ Aurora0001 Bir formu işlemeniz gereken bir durumda, ağ isteklerini tek başına yapacak bir düzenleme formu söyleyin, ancak girdileri bu bileşene sahne olarak gelecek değerlerle başlatmanız gerekir. Formu dinamik tutmak için bu değerlerin devlette tutulması gerekir.
Eric McWinNEr

Yanıtlar:


196

Hiçbir zaman duruma geçmeyen özellikleri kopyalamanın bir anti-desen olduğu belirtilmelidir (sadece bu durumda .props'a doğrudan erişin). Sonunda değişecek ancak .props değerinden başlayan bir durum değişkeniniz varsa, bir yapıcı çağrısına bile ihtiyacınız yoktur - bu yerel değişkenler, üst öğenin yapıcısına yapılan bir çağrıdan sonra başlatılır:

class FirstComponent extends React.Component {
  state = {
    x: this.props.initialX,
    // You can even call functions and class methods:
    y: this.someMethod(this.props.initialY),
  };
}

Bu, aşağıdaki @ joews tarafından verilen yanıtın kısayoluna eşdeğerdir. Sadece es6 transpillerin daha yeni sürümlerinde çalışıyor gibi görünüyor, bazı webpack kurulumlarında bununla ilgili sorunlar yaşadım. Bu sizin için işe yaramazsa, babel eklentisini eklemeyi deneyebilir babel-plugin-transform-class-propertiesveya aşağıdaki @joews tarafından steno olmayan sürümü kullanabilirsiniz.


1
Cevabınızın @joews cevabından nasıl farklı olduğunu daha fazla açıklayabilir misiniz?
Jalal

3
"Yaptığınız tek şey değişkenleri ayarlıyorsa yapıcı çağrısını atlayabilirsiniz."
Zane Hooper

3
Eğer işe yaramazsa, muhtemelen bu babel eklentisini "babel-plugin-transform-class-properties" kurmanız gerekir.
Faheem

2
Devletin başlatma işleminden sonra desteklere bağlı olmadığı anlaşılırsa , durumu sahne konumlarından başlatmak bir anti-desen değildir. İkisini senkronize tutmaya çalışıyorsanız, bu bir anti-desen.
Yatrix

1
@ ak85 aynı sözdizimidir ancak bunun yerine bunu kullanırsınız. Bu sözdizimi, sınıf oluşturma işlemi sırasında durumu ayarlamak için kullanılan kısa bir sözdizimidir (ve durum dışındaki değişkenler için de kullanılabilir)
Zane Hooper

137

setStateBir Bileşenleri aramanız gerekmez constructor- this.statedoğrudan ayarlamak deyimseldir :

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      x: props.initialX
    };
  }
  // ...
}

Bkz. Tepki belgeleri - Bir Sınıfa Yerel Durum Ekleme .

Açıkladığınız ilk yöntemin bir avantajı yoktur. Bileşeni ilk kez monte etmeden hemen önce ikinci bir güncelleme ile sonuçlanacaktır.


4
İyi cevap. Bunun sadece başlangıç ​​durumunu ayarlamak için olduğunu belirtmek gerekebilir; setStatebaşka bir yerde mutasyona uğrarsanız hala kullanmanız gerekir , aksi takdirde değişiklikler gerçekleşmeyebilir.
Aurora0001

Tekrar teşekkürler jowes, ikinci dokümantasyon facebook.github.io/react/docs/…
Levy Moreira

(üzgünüm enter tuşuna basıyorum ..) Biz sahne durumunu ayarlamak için getInitialState kullanmalıyız, daha karmaşık görevlerde, eğer basitse bunu sadece kullanabiliriz. render render içine, doğru?
Levy Moreira

1
Marjinal bir notta: super(props)yapıcıda kullanın . SO
cutemachine ile

2
Joews'ün önerisi çoğu durumda işe yarar, ancak buna doğrudan sahne gönderme konusunda dikkatli olun. Sahne malzemelerini this.state'e kopyalamak aslında tek bir gerçek kaynağıdır ( medium.com/react-ecosystem/… ). Ayrıca, Dan Abramov bir zamanlar sahne değerlerinin devlette saklanmamasını önerdi. ( twitter.com/dan_abramov/status/749710501916139520/photo/1 ).
Hiroki

33

React 16.3 alfa güncellemesistatic getDerivedStateFromProps(nextProps, prevState) ( docs ) yerine geçmiştircomponentWillReceiveProps .

getDerivedStateFromProps, bir bileşen başlatıldıktan sonra ve yeni sahne aldığında çağrılır. Durumu güncellemek için bir nesne döndürmeli veya yeni desteklerin durum güncellemesi gerektirmediğini belirtmek için null değerini döndürmelidir.

Bir üst bileşen bileşeninizin yeniden oluşturulmasına neden oluyorsa, sahne donanımı değişmemiş olsa bile bu yöntemin çağrıldığını unutmayın. Yalnızca değişiklikleri işlemek istiyorsanız yeni ve önceki değerleri karşılaştırmak isteyebilirsiniz.

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

Bu nedenle doğrudan erişimi yok, statik this(ancak erişimi var prevState, normalde ekli şeyleri saklamak hangi thisörn refs)

@ nerfologist'in yorumdaki düzeltmesini yansıtacak şekilde düzenlendi


3
Sadece netleştirmek için adlandırılana getDerivedStateFromProps(Dikmeler sermaye harfi işaretlemek) ve parametreler şunlardır nextProps, prevState(değil nextState): reactjs.org/docs/...
nerfologist

1
Vaov! güncellenmiş sahne alındığında durumu güncellemek için bunu kullanabiliriz !
Aromal Sasidharan

2
getDerivedStateFromPropsHer zaman ilk oluşturma işleminden önce çağrıldığını düşünerek, yapıcıda ilk durumu oluşturmamız gerekiyor mu?
bvdb

19

Tüm destekleri aynı isimleri belirtmek ve tutmak için aşağıdaki gibi kısa formu kullanabilirsiniz.

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}

1
durum olarak değişmeyen özellikleri kopyalamak için bir anti-desendir. Bileşeninizin hangi alanları kullandığını açıkça tanımlamak daha iyidir.
Michael Freidgeim

5

kurucu içindeki durum verilerini böyle ayarlayın

constructor(props) {
    super(props);
    this.state = {
      productdatail: this.props.productdetailProps
    };
  }

u props aracılığıyla side componentDidMount () yönteminde ayarlanırsa çalışmaz.




1

ComponentWillReceiveProps kullanabilirsiniz.

constructor(props) {
    super(props);
    this.state = {
      productdatail: ''
    };
  }

    componentWillReceiveProps(nextProps){
        this.setState({ productdatail: nextProps.productdetailProps })
    }

1
componentWillReceiveProps Kullanımdan kaldırıldı Gelecek sürümler için kullanılamaz
Vivek Ghanchi

1

EĞER sen başlatmak zaman dikkatli olmak zorunda statedan propsyapıcısı içinde. Yenisi ile propsdeğiştirilse bile , devlet değişmeyecek çünkü mount bir daha asla gerçekleşmeyecek. Bunun getDerivedStateFromPropsiçin var.

class FirstComponent extends React.Component {
    state = {
        description: ""
    };

    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.description !== nextProps.description) {
          return { description: nextProps.description };
        }

        return null;
    }

    render() {
        const {state: {description}} = this;    

        return (
            <input type="text" value={description} /> 
        );
    }
}
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.