Использование ресурсов REST перед рендерингом в React.js

У меня есть компоненты React, которые используют внешний веб-сервис для получения данных для рендеринга. Я хочу, чтобы данные загружались ДО рендеринга, потому что я хочу, чтобы они индексировались поисковыми системами.

Вот моя составляющая:

class AboutPage extends React.Component {

    async componentWillMount() {
        let response = await EventWS.doSearch();

        this.setState({
            eventList : response.data
        })
    }

    render() {
        /* ... */
    }
}

(Я пытался использовать async / await, потому что думал, что это может помочь, но нет).

При попытке загрузить страницу с рендерингом на стороне сервера я получил предупреждение:

Warning: setState(...): Can only update a mounting component. This usually means you called setState() outside componentWillMount() on the server. This is a no-op. Please check the code for the FluxContainer(AboutPage) component.

Указывает, что setState выполняется ПОСЛЕ завершения componentWillMount.

В моем конкретном случае, как лучше всего справиться с этим? Есть ли простой способ синхронного вызова ajax? Это рекомендуется делать?

Спасибо.

РЕДАКТИРОВАТЬ: я нашел библиотеку, которая позволяет выполнять синхронный вызов: https://github.com/ForbesLindesay/sync-request

Но в нем говорится, что он не очень подходит для производства. Так что я немного разочарован.


person Oreste Viron    schedule 21.07.2017    source источник
comment
В этом билете обсуждается async componentWillMount github.com/facebook/react/issues/1739. Может ты найдешь там указатели на сомы   -  person jontro    schedule 21.07.2017


Ответы (2)


У меня нет большого опыта работы с Flux, но похоже, что вы должны сделать это в методе componentDidMount.

person Robert Fines    schedule 21.07.2017
comment
Я думаю, что componentDidMount всегда выполняется на стороне клиента. ComponentWillMount выполняется на стороне сервера, поэтому именно он должен использоваться для рендеринга на стороне сервера. - person Oreste Viron; 21.07.2017
comment
Без смонтированного компонента вы не можете установить состояние, поэтому вам придется найти другой способ передать данные вашему компоненту. Может быть, компонент-контейнер, который передает опору функции, которую вы должны вызвать после завершения асинхронного выполнения? - person Robert Fines; 21.07.2017
comment
Проблема не в том, что компонент монтируется. Проблема в том, что вызов ajax разрешается после завершения функции componentWillMount. Если я использую контейнер, у меня будет та же проблема: как загрузить ответ перед рендерингом контейнера? - person Oreste Viron; 21.07.2017

Вы можете использовать обещание Axios на основе получить в componentDidMount, чтобы реализовать его, например, вы можете сослаться на Handling Events In React и ниже пример кода:

constructor(props) {
   super(props);
   this.state = {eventList: []};
   this.Axios = axios.create();
}

componentDidMount() {
        let _this = this;
        this.Axios.get('/your/rest/url')
           .then(function (response) {
               console.log(response);
               _this.setState({eventList: response.data});
           }).catch(function (error) {
               console.log(error);
           });
}

Или, если вы уже используете Axios, убедитесь, что EventWS.doSearch() возвращает Promise вам и вызовите его в componentDidMount следующим образом:

constructor(props) {
   super(props);
   this.state = {eventList: []};
}

componentDidMount() {
        let _this = this;
        EventWS.doSearch().then(function (response) {
            console.log(response);
            _this.setState({eventList: response.data});
        }).catch(function (error) {
            console.log(error);
        });
}
person Arpit Aggarwal    schedule 21.07.2017
comment
Спасибо, но я думаю, что вы неправильно поняли вопрос. Фактически я уже использую Axios, даже если он скрыт классом EventWS. - person Oreste Viron; 21.07.2017
comment
затем убедитесь, что EventWS.doSearch(); вернет вам обещание и вызовите его в componentDidMount - person Arpit Aggarwal; 21.07.2017
comment
Это не вопрос. - person Oreste Viron; 21.07.2017