0

I'm trying to make weather app with react, and I want to change city by typing the name of the city in input. I have function that must change state:

 update( e ){
      this.setState({cityName: e.target.value})
    }

And in render function I have this:

return <div id="layout-content" className="layout-content-wrapper">
                    <input type="text"
                    onChange={this.update.bind(this)}/>
                    <div className="panel-list">{ persons }</div>
                    <h1>{this.state.coord.lon}</h1>
                    <h1>{this.state.cityName}</h1>       //output my city name

And I have function where I pass my city name var in URL to api:

UserList(city = this.state.cityName){
      let apiKey = 'c24bda9c5812d6be82860b70c35d41a5';
      let url = 'http://api.openweathermap.org/data/2.5/weather?q=';
      let weatherURL = 'http://api.openweathermap.org/data/2.5/weather?q='+city+'&appid=c24bda9c5812d6be82860b70c35d41a5';
    return $.getJSON(weatherURL).then((response) => {
        this.setState({coord: response.coord});
        this.setState({person: response.weather});
    });
  }
        </div>

But it not change weather forecast. Why it not changes? All code:

class App extends React.Component {
  constructor(props){
    super();
    this.state = {
      person: [],
        coord: [],
        cityName: 'London'
    };
  }

    componentDidMount() {
        this.UserList();
    }

    update( e ){
      this.setState({cityName: e.target.value})
    }

  UserList(city = this.state.cityName){
      let apiKey = 'c24bda9c5812d6be82860b70c35d41a5';
      let url = 'http://api.openweathermap.org/data/2.5/weather?q=';
      let weatherURL = 'http://api.openweathermap.org/data/2.5/weather?q='+city+'&appid=c24bda9c5812d6be82860b70c35d41a5';
    return $.getJSON(weatherURL).then((response) => {
        this.setState({coord: response.coord});
        this.setState({person: response.weather});
    });
  }

    render() {
        const persons = this.state.person.map((item) => {
            return <div>
              <h1>{item['id']}</h1>
              <span>{item['main']}</span>

            </div>
        });

        return <div id="layout-content" className="layout-content-wrapper">
                    <input type="text"
                    onChange={this.update.bind(this)}/>
                    <div className="panel-list">{ persons }</div>
                    <h1>{this.state.coord.lon}</h1>
                    <h1>{this.state.cityName}</h1>
        </div>
    }
}

export default App;

1 Answer 1

4

componentDidMount will only be called one time in the components lifecycle - right after the component is initially mounted. If you want your update method to trigger UserList, you need to call UserList after your setState call completes in update

update( e ){
  this.setState({cityName: e.target.value}, () => {
    this.UserList(this.state.cityName);
  });
}

You could also accomplish this by inspecting prev/current state in componentDidUpdate. Please note if you take this approach: if you ever update the cityName state item within UserList it will cause an infinite loop.

componentDidUpdate(prevProps, prevState) {
   if (prevState.cityName !== this.state.cityName) {
      this.UserList(this.state.cityName);
   }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.