Как я могу управлять данными из вызова API в React? - PullRequest
0 голосов
/ 12 июля 2020

Я вызываю api для openWeatherapi, но проблема в том, что данные «не определены», пока она не будет решена. Поэтому, когда я вызываю api в ComponentDidMount и устанавливаю данные в состояние, состояние некоторое время не определено, пока не будут получены данные. Проблема в том, что тем временем, если я попытаюсь что-либо сделать с данными, которые я получаю, я не могу "Dosomething" приличия undefined, и все рушится. Как мне обойти это?

У меня есть погодный виджет, и я хочу передать данные о погоде из вызова API. Название города включает континент, поэтому, если я хочу выполнить для него .split (), я получаю сообщение об ошибке, потому что значение сначала не определено.

Вот код панели

import React, { PureComponent } from 'react';
import axios from 'axios';
import PropTypes from 'prop-types';
import brand from 'dan-api/dummy/brand';
import { Helmet } from 'react-helmet';
import { withStyles } from '@material-ui/core/styles';
import Hidden from '@material-ui/core/Hidden';
import Grid from '@material-ui/core/Grid';
import moment from 'moment';
import Divider from '@material-ui/core/Divider';
import {
  SliderWidget,
  CounterIconsWidget,
  PerformanceChartWidget,
  DateWidget,
  TaskWidget,
  WeatherWidget,
  ContactWidget,
  TimelineWidget,
  FilesWidget,
} from 'dan-components';
import ScrollableTabs from '../UiElements/demos/Tabs/ScrollTabs';
import styles from './dashboard-jss';

class PersonalDashboard extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      scheduleToday: [],
      scheduleTomorrow: [],
      weather: {},
    };
  }

  fetchTodaySchedule = () => {
    axios
      .get(`/api/total/schedule/?day=${moment().format('llll')}`)
      .then(response => {
        this.setState({
          scheduleToday: response.data[0].result,
        });
      })
      .catch(error => {
        console.log(error);
      });
  };

  fetchTomorrowSchedule = () => {
    axios
      .get(
        `api/total/schedule/?day=${moment()
          .add(1, 'days')
          .format('llll')}`,
      )
      .then(response => {
        this.setState({
          scheduleTomorrow: response.data[0].result,
        });
      })
      .catch(error => {
        console.log(error);
      });
  };

  fetchWeather = async () => {
    axios
      .get(`api/total/weather`)
      .then(response => {
        this.setState({
          weather: response.data,
        });
      })
      .catch(error => {
        console.log(error);
      });
  };

  async componentWillMount() {
    await this.fetchWeather();
    this.fetchTodaySchedule();
    this.fetchTomorrowSchedule();
  }

  render() {
    const title = brand.name + ' - Personal Dashboard';
    const description = brand.desc;
    const { classes } = this.props;
    return (
      <div>
        <Helmet>
          <title>{title}</title>
          <meta name="description" content={description} />
          <meta property="og:title" content={title} />
          <meta property="og:description" content={description} />
          <meta property="twitter:title" content={title} />
          <meta property="twitter:description" content={description} />
        </Helmet>
        {/* 1st Section */}
        <Grid container spacing={3} className={classes.root}>
          <Grid item md={6} xs={12}>
            <CounterIconsWidget />
          </Grid>
          <Grid item md={6} sm={12} xs={12}>
            <div className={classes.sliderWrap}>
              <SliderWidget />
            </div>
          </Grid>
        </Grid>
        <Divider className={classes.divider} />
        {/* 2nd Section */}
        <Grid container spacing={2} className={classes.root}>
          <Grid item xs={12}>
            <PerformanceChartWidget />
          </Grid>
        </Grid>
        {/* 3rd Section */}
        <Grid container spacing={3} className={classes.root}>
          <Grid item md={6} xs={12}>
            <Divider className={classes.divider} />
            {/* <ScrollableTabs /> */}
            <ContactWidget />
            <Divider className={classes.divider} />
            <TaskWidget />
          </Grid>
          <Grid item md={6} xs={12}>
            <Hidden mdDown>
              <Divider className={classes.divider} />
            </Hidden>
            <WeatherWidget weatherData={this.state.weather} />
            <Divider className={classes.divider} />
            <DateWidget />
            <Divider className={classes.divider} />
            <TimelineWidget />
          </Grid>
        </Grid>
        <Divider className={classes.divider} />
        <FilesWidget />
      </div>
    );
  }
}

PersonalDashboard.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(PersonalDashboard);

а это компонент погодного виджета

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import 'dan-styles/vendors/react-weather/GenericWeather.css';
import classNames from 'classnames';
import styles from './widget-jss';

function WeatherWidget(props) {
  const { status, classes, temp, city, weatherData } = props;
  const cls = classNames('weather-icon', status);
  const bg = classNames(classes.weathercard, status === 'sun' ? classes.sun : classes.cloud);
  return (
    <div className={bg}>
      <div className="wheater-wrap">
        <div className={cls} />
        <h1>{temp}º</h1>
        <p>{weatherData.timezone}</p>
      </div>
    </div>
  );
}

WeatherWidget.propTypes = {
  classes: PropTypes.object.isRequired,
  city: PropTypes.string,
  temp: PropTypes.number,
  status: PropTypes.string,
};

WeatherWidget.defaultProps = {
  city: 'Bucharest',
  temp: 28,
  status: 'sun', // cloud and sun
};

export default withStyles(styles)(WeatherWidget);

введите описание изображения здесь

Ответы [ 2 ]

1 голос
/ 12 июля 2020
async componentDidMount() {
  try {
    const [tickets, alerts, calls, weather, schedToday, schedTomorrow] = await Promise.all([
      axios.get('api/total/tickets'),
      axios.get('api/total/alerts'),
      axios.get('api/total/avaya/logs'),
      axios.get('api/total/weather'),
      axios.get(`/api/total/schedule/?day=${today}`),
      axios.get(`/api/total/schedule/?day=${tomorrow}`),
    ]);

    this.setState({
      tickets: tickets.data.tickets,
      alerts: alerts.data,
      calls: calls.data,
      weather: weather.data,
      scheduleToday: schedToday.data[0].result,
      scheduleTomorrow: schedTomorrow.data[0].result
    });
  } catch (err) {
    console.error(err);
  }
}
0 голосов
/ 12 июля 2020

В итоге я сделал это таким образом и использовал asyn c componentDidMount.

Пока вроде все работает нормально.

 async componentDidMount() {
    const ticketsPromise = await axios.get('api/total/tickets');
    const alertsPromise = await axios.get('api/total/alerts');
    const callsPromise = await axios.get('api/total/avaya/logs');
    const weatherPromise = await axios.get('api/total/weather');
    const scheduleTodayPromise = await axios.get(`/api/total/schedule/?day=${today}`);
    const scheduleTomorrowPromise = await axios.get(`/api/total/schedule/?day=${tomorrow}`);

    const resolves = await Promise.all([
      ticketsPromise.data,
      alertsPromise.data,
      callsPromise.data,
      weatherPromise.data,
      scheduleTodayPromise.data[0].result,
      scheduleTomorrowPromise.data[0].result,
    ]);

    const [ticketsData, alertsData, callsData, weatherData, schedTodayData, schedTomorrowData] =
      resolves || [];

    this.setState({ tickets: ticketsData.tickets });
    this.setState({ alerts: alertsData });
    this.setState({ calls: callsData });
    this.setState({ weather: weatherData });
    this.setState({ scheduleToday: schedTodayData });
    this.setState({ scheduleTomorrow: schedTomorrowData });
  }
...