Reactjs eşzamansız bileşen oluşturma


83

Ajax isteğim tamamlandıktan sonra bileşenimi oluşturmak istiyorum.

Kodumu aşağıda görebilirsiniz

var CategoriesSetup = React.createClass({

    render: function(){
        var rows = [];
        $.get('http://foobar.io/api/v1/listings/categories/').done(function (data) {
            $.each(data, function(index, element){
                rows.push(<OptionRow obj={element} />);
            });
           return (<Input type='select'>{rows}</Input>)

        })

    }
});

Ancak aşağıdaki hatayı alıyorum çünkü ajax isteğimin done yöntemi içinde render döndürüyorum.

Uncaught Error: Invariant Violation: CategoriesSetup.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

Oluşturmaya başlamadan önce ajax isteğimin bitmesini beklemenin bir yolu var mı?


3
Ayrıca, küçük bir nitpick, ancak bir render () rutininde veri alımı gerçekten iyi bir fikir değildir. Geri kalanını oluşturmak ve soyutlamak için render () kullanmaya devam edin. Ayrıca, bu verileri bileşen her oluşturulduğunda değil, yalnızca bir kez almak isteyebilirsiniz.
Phil Cooper

Yanıtlar:


132

Bunu halletmenin iki yolu vardır ve hangisini seçeceğiniz, hangi bileşenin veriye sahip olması gerektiğine ve yükleme durumuna bağlıdır.

  1. Ajax isteğini üst öğeye taşıyın ve bileşeni koşullu olarak oluşturun:

    var Parent = React.createClass({
      getInitialState: function() {
        return { data: null };
      },
    
      componentDidMount: function() {
        $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {
          this.setState({data: data});
        }.bind(this));
      },
    
      render: function() {
        if (this.state.data) {
          return <CategoriesSetup data={this.state.data} />;
        }
    
        return <div>Loading...</div>;
      }
    });
    
  2. Ajax isteğini bileşende tutun ve yüklenirken başka bir şeyi koşullu olarak oluşturun:

    var CategoriesSetup = React.createClass({
      getInitialState: function() {
        return { data: null };
      },
    
      componentDidMount: function() {
        $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {
          this.setState({data: data});
        }.bind(this));
      },
    
      render: function() {
        if (this.state.data) {
          return <Input type="select">{this.state.data.map(this.renderRow)}</Input>;
        }
    
        return <div>Loading...</div>;
      },
    
      renderRow: function(row) {
        return <OptionRow obj={row} />;
      }
    });
    

6
2017'de bu cevaba rastladım, bunlar en iyi iki çözüm hala kullanmak için en iyisi mi?
Dan

@Dan React, kullanıcı arayüzünü sahne ve duruma göre oluşturur, böylece temel kavram aynı kalacaktır - Ajax isteğini yapın, durumu ayarlayın ve bir şeyi yeniden oluşturun. Bununla birlikte, daha yüksek dereceden bileşenler gibi modeller daha popüler hale geldi ve karmaşıklıkları nasıl soyutlayabileceğini gösterdi.
Michelle Tilley

1
if (this.state.data)olmalıdır if (this.state && this.state.data)bazen devlet boş olabilir çünkü.
Timo

@Timo Hm ne durumda olurdu this.stateolmak null?
Michelle Tilley

6
@Timo yapıcıdaki durumu başlat
Louis

8

Bileşenlerin eşzamansız oluşturulmasının temel örneği aşağıdadır:

import React                from 'react';
import ReactDOM             from 'react-dom';        
import PropTypes            from 'prop-types';

export default class YourComponent extends React.PureComponent {
    constructor(props){
        super(props);
        this.state = {
            data: null
        }       
    }

    componentDidMount(){
        const data = {
                optPost: 'userToStat01',
                message: 'We make a research of fetch'
            };
        const endpoint = 'http://example.com/api/phpGetPost.php';       
        const setState = this.setState.bind(this);      
        fetch(endpoint, {
            method: 'POST',
            body: JSON.stringify(data)
        })
        .then((resp) => resp.json())
        .then(function(response) {
            setState({data: response.message});
        });
    }

    render(){
        return (<div>
            {this.state.data === null ? 
                <div>Loading</div>
            :
                <div>{this.state.data}</div>
            }
        </div>);
    }
}
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.