Асинхронний візуалізація компонентів Reactjs


83

Я хочу зробити свій компонент після того, як мій запит ajax буде виконано.

Нижче ви можете побачити мій код

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

        })

    }
});

Але я отримую помилку нижче, тому що я повертаю візуалізацію всередині зробленого методу мого запиту ajax.

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

Чи є спосіб дочекатися закінчення мого запиту ajax перед початком відтворення?


3
Крім того, невеликий шматочок, але пошук даних у процедурі render (), насправді не є чудовою ідеєю. Тримайте render () для рендерингу та абстрагуйте решту. Крім того, вам може знадобитися отримати ці дані лише один раз, а не кожен раз, коли компонент відображається.
Філ Купер,

Відповіді:


132

Є два способи вирішити це, і який ви виберете, залежить від того, який компонент повинен володіти даними та стан завантаження.

  1. Перемістіть запит Ajax у батьківський і умовно візуалізуйте компонент:

    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 у компоненті та ретельно відтворюйте щось інше під час його завантаження:

    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 році, чи ці два найкращі рішення все ще залишаються найкращими для використання?
Ден,

@Dan React відображає інтерфейс користувача на основі реквізиту та стану, тому основна концепція залишиться незмінною - виконайте запит Ajax, встановіть деякий стан і повторно рендеріть щось. Однак такі моделі, як компоненти вищого порядку, стали більш популярними, демонструючи, як можна абстрагувати складності.
Мішель Тіллі,

1
if (this.state.data)повинно бути, if (this.state && this.state.data)тому що іноді стан може бути нульовим.
Тимо

@ Тимо Хм, в якому випадку це було this.stateб null?
Мішель Тіллі,

6
@Timo ініціалізує стан у конструкторі
Луї

8

Основний приклад асинхронного візуалізації компонентів наведено нижче:

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>);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.