2014-11-28 22 views
51

Chcę renderować mój komponent po wykonaniu żądania ajax.Reactjs asynchroniczne renderowanie komponentów

Poniżej można zobaczyć mój kod

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>) 

     }) 

    } 
}); 

ale pojawia się błąd poniżej ponieważ wracam renderowanie wewnątrz wykonanej metodą mojego ajax żądanie.

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

Czy istnieje sposób, aby czekać na mój ajax żądanie, aby zakończyć przed renderowania startowym?

+2

Również mały dziurkacz, ale pobieranie danych w procedurze render() nie jest świetnym pomysłem. Zachowaj render() do renderowania, a resztę usuń. Co więcej, dane mogą być pobierane tylko raz, a nie za każdym razem, gdy komponent jest renderowany. –

Odpowiedz

90

Są na to dwa sposoby, a wybór zależy od tego, który komponent powinien być właścicielem danych i stanu ładowania.

  1. Przesuń żądania Ajax do rodziców i warunkowo renderowania komponentu:

    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. Utrzymuj żądania Ajax w komponencie i uczynić coś innego warunkowo natomiast to ładowania:

    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} />; 
        } 
    }); 
    
+4

Natknąłem się na tę odpowiedź w 2017 roku, czy te dwa najlepsze rozwiązania wciąż są najlepsze w użyciu? – Dan

+0

@Dan React renderuje UI na podstawie rekwizytów i stanów, więc podstawowa koncepcja pozostanie taka sama - wykonaj żądanie Ajax, ustaw stan i ponownie renderuj coś. Jednak wzorce takie jak komponenty wyższego rzędu stały się bardziej popularne, pokazując, jak można uprościć zawiłości. –

+0

'jeśli (this.state.data)' powinno być 'if (this.state && this.state.data)' ponieważ czasami stan może mieć wartość null. – Timo