React - 使用用户输入进行 API 调用的正确方法是什么?

React - What is the correct way to make an API call with user input?

我对 React 比较陌生,正在构建一个简单的天气应用程序来帮助我学习。我已经广泛阅读了文档,但我仍然被卡住了。我的应用程序有用户输入,他们可以在其中使用 OpenWeatherMap API 搜索城市的天气预报。目前,我的组件状态如下所示:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoaded: false,
      inputText: '',
      data: {
        dayOne: [],
        dayTwo: [],
        dayThree: [],
        dayFour: [],
        dayFive: [],
        daySix: []
      }
    };
  }
}

一旦他们点击按钮获取数据,我就使用带有 axios 的 handleSubmit() 方法从 API 中获取数据。这成功填充了组件状态。

例如,在 React Dev Tools 中我可以看到我在 this.state.data.dayOne[0] 中得到了以下数据,这正是我想要的:

0: {
  weather_data: {
    cityName: "London"
    date: "2019-08-05"
    description: "scattered clouds"
    temp: 21.79
    tempMax: 21.79
    tempMin: 21.41
    time: "18:00"
    weatherIcon: "03d"
  }
} 

在我的用户输入组件下方,我有一个显示当天当前天气数据的面板组件。为了清楚起见,我在这里减小了组件的大小:

// In CurrentWeatherDisplay.js:

class CurrentWeatherDisplay extends Component {
  render() {
    return (
      <div className="col-12 border border-info">
        <div className="row">
          <div className="col-6 py-4">
            <p className="mb-0 h6">City name:</p>
          </div>
          <div className="col-6 py-4">
            <p className="mb-0 h6">{this.props.data.dayOne[0].weather_data.cityName}</p>
          </div>
        </div>
      </div>
    );
  }
}

我遇到的问题是 this.props.data.dayOne[0].weather_data.cityName 在调用 API 之前不存在,因此应用程序无法呈现。我已经阅读了 React 文档,它说要使用 componentDidMount() 生命周期方法。但在他们的示例中,这是一个立即发生的 API 调用 - https://reactjs.org/docs/faq-ajax.html

我的应用程序不同,因为我在页面加载后更新状态,并且仅当用户提交表单时。有什么想法可以纠正我的应用程序的结构吗?

如果你想把加载的代码放到一个回调函数中而不是componentDidMount中也可以。你应该从那篇文章中学到的主要东西是有一个开始为空的状态值(或者以某种其他方式指示数据尚未加载),以及一个渲染函数,当它看到状态时知道要渲染什么空的。

例如,如果您的状态中有一个名为 isLoaded 的标志,您的渲染函数可以检查 isLoaded 是否为 false,并且当它发现它时 returns 一些占位符。

render() {
  if (!this.state.isLoaded) {
    return <div>Loading...</div>
  }

  // else, return the populated component
}

然后当你想加载数据时(在他们的例子中是 componentDidMount,在你的例子中是 handleSubmit),然后调用 this.setState。新状态将导致组件重新渲染,并且您的渲染函数现在 returns 与以前不同,使用新数据。