javascriptjqueryajaxreactjs

Run an AJAX call on a click event - using React.js


I'm creating a web app that will make an AJAX call to the OpenWeather API to grab a city's weather data - based on the city the user clicked on.

I'm using React for my front-end, Node.js/Express for my backend - but am having trouble implementing the correct set-up of how to make the API call based on the user's clicks.

How can I refactor my code to base it on clicks?

This is what I have so far (JSBIN: https://jsbin.com/mayejej/edit?html,js,output) - which is hardcoded to "London" at the moment:

 var data = [
    {name: "London"},
    {name: "Tokyo"},
    {name: "NYC"}
];

var MusicBox = React.createClass({
    render: function() {
        return (
            <div className="musicBox">
                <h1>This is the music box</h1>
                <CityList data={this.props.data} />
            </div>
        );
    }
});

var CityList = React.createClass({
    getInitialState: function() {
        return {data: []};
    },
    componentDidMount: function() {
        $.ajax({
            url: 'http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=bd82977b86bf27fb59a04b61b657fb6f',
            method: 'GET',
            success: function(result) {
                this.setState({data: result});
            }.bind(this)
        });
    },
    render: function() {
        var cityNodes = this.state.data.map(function(city) {
            return (
                <City info={city} />
            );
        });
        return (
            <div className="cityList">
                {cityNodes}
            </div>
        );
    }
});

var City = React.createClass({
    render: function() {
        return (
            <div className="city">
                <h2 className="cityName">
                    {this.props.info.name}
                </h2>
                {this.props.children}
            </div>
        );
    }
});

var CityInfo = React.createClass({
    getInitialState: function() {
        return {data: {}};
    },
    componentDidMount: function() {
        $.ajax({
            url: 'http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=bd82977b86bf27fb59a04b61b657fb6f',
            method: 'GET',
            success: function(result) {
                this.setState({data: result});
            }.bind(this)
        });
    },

    render: function() {
        return (
            <div>
                <h3>{this.state.data.name}</h3>
            </div>
        );
    }
});


ReactDOM.render(
    <MusicBox data={data} />,
    document.getElementById('content')
);

Solution

  • what you want to do is have a button that the user can click on. this will be used for your ajax request instead of in the componentDidMount.

    in your render add a button

    <button onClick={this.loadCityInfo} data-city={this.props.info.name}>{this.props.info.name}</button>
    

    your function should look like this

    loadCityInfo: function(e){
        var city = $(e.currentTarget).data('city');
        // now make your ajax request with the city's name passed to pull out the correct data
    }