简体   繁体   English

状态更改时,React组件不会重新呈现

[英]React component doesn't re-render when state changes

I am making a react app in which a user can input the identifier for an airport, and the app will get the respective weather data from a web API and display it in a table (ex: CYOW --> http://avwx.rest/api/metar/CYOW ). 我正在制作一个反应应用程序,用户可以在其中输入机场的标识符,应用程序将从Web API获取相应的天气数据并将其显示在表格中(例如:CYOW - > http:// avwx。 rest / api / metar / CYOW )。 I have gotten to the point where the 'url' state which specifies the API endpoint of the airport the user searches, is updating when they input the value, however the component is not re-rendering when that state changes and therefore my table is not updating. 我已经到了指定用户搜索机场的API端点的'url'状态,在输入值时更新,但是当该状态发生变化时组件不会重新呈现,因此我的表不是更新。 What am I doing wrong here? 我在这做错了什么? Sorry for the terrible code, this is my first go at React + JS. 对不起,可怕的代码,这是我第一次去React + JS。 Thanks. 谢谢。

import React, { Component } from 'react';
import {Icon, Label, Menu, Table, Form, Button} from 'semantic-ui-react';

export default class Stationsearch extends React.Component {

    constructor(props){
        super(props);
        this.state = {
            url: 'http://avwx.rest/api/metar/CYOW',
            data: {},
            Station: '',
            Timestamp: '',
            Time: '',
            FlightRules: '',
            Temperature: '',
            Dewpoint: '',
            Visibility: '',
            WindDir: '',
            WindGust: '',
            WindSpeed: '',
            WindVar: [],
            CloudList: [],
            Raw: '',
            userInput: '',
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    componentDidMount(){

        fetch(this.state.url)
        .then(d => d.json())
        .then(d => {
            this.setState({
                data: d, 
                Station: d.Station,
                Timestamp: d.Meta.Timestamp,
                Time: d.Time,
                FlightRules: d["Flight-Rules"],
                Temperature: d.Temperature,
                Dewpoint: d.Dewpoint,
                Visibility: d.Visibility,
                WindDir: d["Wind-Direction"],
                WindGust: d["Wind-Gust"],
                WindSpeed: d["Wind-Speed"],
                WindVar: d["Wind-Variable-Dir"],
                CloudList: d["Cloud-List"],
                Raw: d["Raw-Report"],
            })
        })
    }

    handleChange(event){
        this.setState({userInput: event.target.value});
    }

    handleSubmit(event){
        this.setState({url: getUrl(this.state.userInput)});
        event.preventDefault();
    }

render(){
    return (
        <div>
            <Form onSubmit={this.handleSubmit}>
                <Form.Field>
                    <Label>Station ID</Label>
                    <input type="text" placeholder="ex: CYOW" onChange={this.handleChange} />
                </Form.Field>
                <Button type='submit'>Search</Button>
            </Form>

            <Table celled striped textAlign="center" color="teal" key="teal" inverted className='table'>
                <Table.Header>
                    <Table.Row>
                    <Table.HeaderCell>Type</Table.HeaderCell>
                    <Table.HeaderCell>Value</Table.HeaderCell>
                    </Table.Row>
                </Table.Header>

                <Table.Body>
                    <Table.Row>
                        <Table.Cell>Station</Table.Cell>
                        <Table.Cell>{ this.state.Station }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Timestamp</Table.Cell>
                        <Table.Cell>{ this.state.Timestamp }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Zulu</Table.Cell>
                        <Table.Cell>{ this.state.Time }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Flight-Rules</Table.Cell>
                        <Table.Cell>{ this.state.FlightRules }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Temperature</Table.Cell>
                        <Table.Cell>{ this.state.Temperature }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Dewpoint</Table.Cell>
                        <Table.Cell>{ this.state.Dewpoint }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Visibility</Table.Cell>
                        <Table.Cell>{ this.state.Visibility }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Wind-Direction</Table.Cell>
                        <Table.Cell>{ this.state.WindDir }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Wind-Speed</Table.Cell>
                        <Table.Cell>{ this.state.WindSpeed }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Wind-Gust</Table.Cell>
                        <Table.Cell>{ this.state.WindGust }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Wind-Variable-Dir</Table.Cell>
                        <Table.Cell>{ this.state.WindVar }</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Clouds</Table.Cell>
                        <Table.Cell>{ getCloudString(this.state.CloudList) }</Table.Cell>
                    </Table.Row>
                </Table.Body>
            </Table>
        </div>
    )}
}

function getCloudString(cloudList) {

    var list = "";

    for (var i=0; i < cloudList.length; i++){
        if (i+1 < cloudList.length){
            list += cloudList[i][0] + " " + cloudList[i][1] + ", ";
        }
        else{
            list += cloudList[i][0] + " " + cloudList[i][1];
        }
    }
    return list;
}

function getUrl(stationID){
    var url = 'http://avwx.rest/api/metar/';
    var id = stationID.toUpperCase();
    url += id;
    return url;
}

It sounds like what you expect is to make another fetch request when the url changes. 这听起来像你期望的是当url改变时发出另一个fetch请求。 In your current code, you only do a fetch inside componentDidMount which only is called once when your component is first created. 在当前代码中,您只在componentDidMount中进行fetch ,只在首次创建组件时调用一次。 Instead, you should call it when the url changes, either in a componentDidUpdate method, or inside handleSubmit . 相反,您应该在url更改时调用它,可以在componentDidUpdate方法中,也可以在handleSubmit

You are only updating the URL in the state of the component but not fetching data for that station id. 您只更新组件状态中的URL,但不获取该站ID的数据。 After updating station id you also need to fetch the data and update it in the state. 更新站ID后,您还需要获取数据并在状态中更新它。 Your component was getting re-rendered but since any data was not changing, your view was not getting updated. 您的组件正在重新呈现,但由于任何数据都没有更改,因此您的视图未得到更新。

  fetchData = () => {
    fetch(this.state.url)
      .then(d => d.json())
      .then(d => {
        this.setState({
          data: d,
          Station: d.Station,
          Timestamp: d.Meta.Timestamp,
          Time: d.Time,
          FlightRules: d["Flight-Rules"],
          Temperature: d.Temperature,
          Dewpoint: d.Dewpoint,
          Visibility: d.Visibility,
          WindDir: d["Wind-Direction"],
          WindGust: d["Wind-Gust"],
          WindSpeed: d["Wind-Speed"],
          WindVar: d["Wind-Variable-Dir"],
          CloudList: d["Cloud-List"],
          Raw: d["Raw-Report"]
        });
      });
  };

  componentDidMount() {
    this.fetchData();
  }

  handleSubmit(event) {
    this.setState({ url: getUrl(this.state.userInput) }, () => {
      this.fetchData();
    });
    event.preventDefault();
  }

Here is the link to the working code. 这是工作代码的链接。 I have made default station id as OMDB and when you search for CYOW data gets updated. 我已将默认工作站ID设为OMDB,当您搜索CYOW时,数据会更新。

https://codesandbox.io/s/3mqp187w1 https://codesandbox.io/s/3mqp187w1

The code is working fine, you're just not fetching again when you submit! 代码工作正常,你提交时只是不再提取!

This is a working version: 这是一个工作版本:

https://codesandbox.io/s/k902vrw7k7 https://codesandbox.io/s/k902vrw7k7

Also make sure to validate the user input, since as it right now you'll crash when they input an invalid station. 还要确保验证用户输入,因为现在它们在输入无效工作站时会崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM