【问题标题】:How can i manipulate data from api call in React?如何在 React 中操作来自 api 调用的数据?
【发布时间】:2020-07-12 09:26:40
【问题描述】:

我对 openWeatherapi 进行了 api 调用,但问题是数据在解决之前是“未定义的”。因此,当我在 ComponentDidMount 中进行 api 调用并将数据设置为状态时,状态在数据进入之前暂时未定义。问题是,与此同时,如果我尝试对获得的数据做任何事情,我将无法“做事”未定义的适当性,整个事情都崩溃了。我该如何解决这个问题?

我有一个天气小部件,我想通过 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);

【问题讨论】:

    标签: javascript node.js reactjs redux axios


    【解决方案1】:
    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);
      }
    }
    

    【讨论】:

      【解决方案2】:

      我最终这样做并使用了异步 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 });
        }
      

      【讨论】:

      • 你做的不对。你不需要使用 Promise.all 因为 ticketPromise.data 不是一个承诺。 ticketPromise 已经不是一个 Promise,因为它是由 await 解决的
      猜你喜欢
      • 2017-05-23
      • 2021-07-02
      • 1970-01-01
      • 2016-06-06
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 2018-08-01
      • 1970-01-01
      相关资源
      最近更新 更多