Как дождаться окончания загрузки данных с помощью async / await в React - PullRequest
0 голосов
/ 28 января 2019

Мой собственный ответ на вопрос работает, комментарий Педрага, который включен в мой ответ, также работает

Я выполняю запрос http и не хочу отображать страницу доответ http возвращен (вызов запроса - getRoadmaps).У меня есть избыточное состояние, называемое «загрузка», чтобы определить, вернулся ли ответ еще?Любые идеи о том, как реализовать это в моем коде?Мои другие избыточные состояния - дорожная карта, которая содержит объект, также называемый дорожной картой (извините за путаницу).

PS Я видел несколько ответов, в которых говорилось о том, что нужно делать (код psuedo): если не загружен экран загрузки дисплея, в противном случае загружается обычный экран при рендеринге.Но моя проблема не существует в рендере, а в componentWillMount (), где я делаю

this.props.getRoadmaps() 

, а затем через 3 строки, где я делаю

console.log(this.displayRoadmap[0].roadmap[0])

, который должен успешно записать дорожную картуесли getRoadmaps () завершена, похоже, что вызывается getRoadmaps (), но затем программа продолжается без полного завершения getRoadmaps (), что приводит к неопределенности моего displayRoadmap.Это также приводит к некоторому странному явлению, например, если я перехожу с одного экрана на этот компонент, он всегда работает, но если я обновляю страницу, он не работает

import React, { Component } from "react";
import Tree from "./Tree";
import TreeSidebar from "./TreeSidebar";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { getRoadmaps } from "../actions/roadmapAction";
class OneRoadmap extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: this.props.roadmap.loading,
      roadmapName: "click a white circle to show more!",
      roadmapImg:
        "https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
      roadmapDetail: [{ text: "Click on something" }, { text: "hi" }],
      treeData: //deleted,just the default big json object
   };
  }

  componentWillMount() {
    this.props.getRoadmaps();

    var location1 = this.props.location.pathname;
    var n = location1.slice(9);

    var current_roadmaps = this.props.roadmap.roadmaps;

    this.displayRoadmap = current_roadmaps.filter(
      eachRoadmap => eachRoadmap._id == n
    );
    // now we have a roadmap
    console.log(this.displayRoadmap[0].roadmap[0]);
    this.setState({ treeData: this.displayRoadmap[0].roadmap[0] });
    console.log("is good");
    console.log(this.props.loading);
  }

  componentDidMount() {}

  handle_on_click_change = d => {
    this.setState({ roadmapName: d.data.name });
    this.setState({ roadmapImg: d.data.img });
    if (d.data.details == undefined) {
      this.setState({
        roadmapDetail: [{ text: "The author did not put anything here" }]
      });
    } else {
      this.setState({ roadmapDetail: d.data.details });
    }
  };

  render() {
    return (
      <div>
        {console.log(this.state.loading)}
        <ul>
          <li styles={{ float: "left" }}>
            <div>
              {console.log(this.state.treeData)}
              <Tree
                on_click_change={this.handle_on_click_change}
                roadmapData={this.state.treeData}
              />
            </div>
          </li>
          <li styles={{ float: "right" }}>
            <div>
              <TreeSidebar
                displayName={this.state.roadmapName}
                displayImg={this.state.roadmapImg}
                displayDetail={this.state.roadmapDetail}
              />
            </div>
          </li>
        </ul>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  roadmap: state.roadmap
});

export default connect(
  mapStateToProps,
  { getRoadmaps }
)(OneRoadmap);

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Я проверил ответ elraphty, потому что он отвечает на часть моего вопроса, и он также хотел, чтобы я проверил его ответ.В любом случае, если у вас возникли проблемы выборки данных и ожидание завершения выборки , вот полный пример того, как я это делаю.Комментарий Предрага Беоканина работает:

fetch('some_url', { method: 'GET' }).then(res = res.json()).then(data => { // some parse here; return parsed}

Вот как я это делаю (используя axios вместо metch, отправляя запрос в другой файл / api / roadmap, а затем используя Redux для обновления магазина.

В OneRoadmap.js, который является компонентом, в который мне нужно извлекать данные, это то, что я вызываю для извлечения данных:

  async componentDidMount() {
await this.props.getRoadmaps();
.....
}

Это позволяет нам запускать this.props.getRoadmaps() и дождитесь завершения строки перед переходом к следующей строке. Если вы не укажете async / await, сработает this.props.getRoadmaps (), но код в componentDidMount () немедленно продолжит работу без this.props.getRoadmaps () завершает выборку данных и затем обновляет состояние. Теперь, конечно, ответ Predrag определенно должен решить эту проблему, но на тот случай, если вы хотите поместить выборку данных и обновление состояния с помощью redux в разных файлах (как я), продолжайте читать .

Это то, что делает getRoadmaps (), в файле с именем RoadmapActions.js:

    export const getRoadmaps = () => dispatch => {
  dispatch(setRoadmapsLoading());
  return axios
    .get("/api/roadmaps")
    .then(res => dispatch({ type: GET_ROADMAPS, payload: res.data }));
};

Это говорит о том, что мы отправим запрос на получение в "/ api / roadmaps", затем возьмем данные возврата из запроса на получение, а затем отправим отправку в хранилище с избыточностью, которое обновит состояние хранилища, и мыв конечном итоге использовать его в OneRoadmap.js.Вот что возвращает запрос / api / roadmaps:

router.get("/", (req, res) => {
Roadmap.find()
.sort({ date: -1 })
.then(roadmaps => res.json(roadmaps));
});

Roadmap.find () заходит в нашу базу данных mongo и получает все элементы дорожной карты, а затем мы возвращаем ее туда, откуда она была вызвана.

С этими возвращенными данными мы отправляем отправку редуктору с этими данными, это то, что делает GET_ROADMAPS (), GET_ROADMAPS находит в roadmapReducer.js:

const initialState = {
  roadmaps: [],
  loading: false,
  current_roadmap: ""
};

export default function(state = initialState, action) {


switch (action.type) {
    case GET_ROADMAPS:
      return {
        ...state,
        roadmaps: action.payload,
        loading: false
      };


}

Тогда вот и все, ваше состояние хранилища резервов обновляется, и, поскольку я подключил OneRoadmap.js к state.roadmap, я могу свободно использовать его в коде.

0 голосов
/ 28 января 2019

Первое и самое важное, не используйте componentWillMount, скорее используйте componentDidMount.UNSAFE_componentWillMount() является устаревшим и будет удален в версии 17. Теперь перейдем к следующему вопросу. Вы хотите отключить страницу, установив для состояния loading значение true.

this.state = {
      loading: true,
      roadmapName: "click a white circle to show more!",
      roadmapImg:
        "https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
      roadmapDetail: [{ text: "Click on something" }, { text: "hi" }],
      treeData: //deleted,just the default big json object
   };

После этого выВы хотите немного настроить метод рендеринга для поддержки условного рендеринга:

render() {
        if (this.state.loading) {
            return <LoadingBar />;
        }
        return (
            <div>
                <ul>
                    <li styles={{ float: 'left' }}>
                        <div>
                            {console.log(this.state.treeData)}
                            <Tree
                                on_click_change={this.handle_on_click_change}
                                roadmapData={this.state.treeData}
                            />
                        </div>
                    </li>
                    <li styles={{ float: 'right' }}>
                        <div>
                            <TreeSidebar
                                displayName={this.state.roadmapName}
                                displayImg={this.state.roadmapImg}
                                displayDetail={this.state.roadmapDetail}
                            />
                        </div>
                    </li>
                </ul>
            </div>
        );
    }

Теперь, когда ваши данные готовы, вы можете просто сделать this.setState({ loading: false }), и метод рендеринга вернет то, что не является панелью загрузки.,Итак, в вашем конкретном случае:

this.setState({ treeData: this.displayRoadmap[0].roadmap[0], loading: false });
0 голосов
/ 28 января 2019

Это может быть легко достигнуто с помощью следующих компонентов.

withLoadingScreen.js

import * as React from "react";

const withLoadingScreen = WrappedComponent => {
  return class LoadingScreen extends React.Component {
    render() {
      if (this.props.loading) return <div className="pre-loader" > Loading... </div>
      return <WrappedComponent {...this.props} />;
    }
  };
};

export default withLoadingScreen;

Используйте HOC следующим образом с вашим компонентом

export default compose(
  connect(mapStateToProps, mapActionCreators),
  withLoadingScreen
)(OneRoadmap)

Вы также можете передать пользовательские параметры в HOC.Для получения дополнительной информации, пожалуйста, перейдите по ссылкам ниже.Внесите необходимые изменения в код, ссылаясь на них.

https://medium.com/@peterpme/learning-higher-order-components-in-react-by-building-a-loading-screen-9f705b89f569

https://medium.com/@Farzad_YZ/handle-loadings-in-react-by-using-higher-order-components-2ee8de9c3deb

0 голосов
/ 28 января 2019

Лично, как я это делаю, я использую стили CSS, я не знаю, если это лучший способ сделать это, но это работает для меня, я сделаю что-то вроде этого

this state = {
  loaderStyle: 'block',
  contentStyle: 'none'

}

componentDidMount() {
    If(this.displayRoadmap[0].length > 0) {
       this.setsState({loaderStyle: 'none', contentStyle: 
          'block:
    } else /// do something

};

В моей функции рендеринга я сделаю это

 <Loader style={{display: this.state.loaderStyle}}/>

 <Content style={{display: this.state.contentStyle}}>. 
 </Content>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...