0

I was building a weather app using OpenWeather API. The API was fetched in Node, then data was passed to React front end, code as follows:

Node index.js

const express = require('express');
const cors = require('cors');
const app = express();
const axios = require('axios');
const dotenv = require('dotenv');
dotenv.config();
const url = `http://api.openweathermap.org/data/2.5/weather?q=london,uk&APPID=${process.env.REACT_APP_WEATHER_API_KEY}`;
app.use(cors());

app.get('/', (req, res) => {
    res.send('go to /weather to see weather')
});

app.get('/weather', (req, res) => {
    axios.get(url)
        .then(response => {res.json(response.data)})
        .catch(error => {
            console.log(error);
        });
})

let port = process.env.PORT || 4000;

app.listen(port, () => {
    console.log(`App running on port ${port} `);
});

The weather data can then be viewed in http://localhost:4000/weather. Then React is used to display the data. Assume there is a simple React component to accept weather input and update state:

React WeatherForm.js

import React from 'react';

class WeatherForm extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            country: '',
            city: ''
        }
    }

    updateLocation(e) {
        this.setState({
            country: e.target.value,
            city: e.target.value
        });
    }

    render() {
        return (
            <form>
                <div className="field">
                    <label className="label">Country</label>
                    <div className="control">
                        <input
                            className="input"
                            type="text"
                            placeholder="Type country name here"
                            onChange={e => this.updateLocation(e)} />
                    </div>
                </div>
                <div className="field">
                    <label className="label">City</label>
                    <div className="control">
                        <input
                            className="input"
                            type="text"
                            placeholder="Type city name here"
                            onChange={e => this.updateLocation(e)} />
                    </div>
                </div>

                <div className="field">
                    <div className="control">
                        <input
                            type='submit'
                            value='Search' />
                    </div>
                </div>
            </form>
        )
    }
}

export default WeatherForm

Question: How can I pass the country and city user input from the React app form to the country and city in the url variable in this line in the Node code?

const url = `http://api.openweathermap.org/data/2.5/weather?q=city,country&APPID=${process.env.REACT_APP_WEATHER_API_KEY}`

UPDATE I have updated the WeatherForm component as follows:

import React from 'react';
import Axios from 'axios';

class WeatherForm extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            country: '',
            city: ''
        }
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit(e) {
        e.preventDefault();
        const url = 'http://localhost:4000/weather';
        const location = {
            country: this.state.country,
            city: this.state.city
        }

        Axios.post(url, location).then((res) => {
            // what should I do here?
        }).catch((e) => {
            console.log(e);
        })
    }

    updateLocation(e) {
        this.setState({
            country: e.target.value,
            city: e.target.value
        });
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <p className="title">Weather</p>
                <p className="subtitle">Check weather by city and country</p>
                <div className="field">
                    <label className="label">Country</label>
                    <div className="control">
                        <input
                            className="input"
                            type="text"
                            placeholder="Type country name here"
                            onChange={e => this.updateLocation(e)} />
                    </div>
                </div>
                <div className="field">
                    <label className="label">City</label>
                    <div className="control">
                        <input
                            className="input"
                            type="text"
                            placeholder="Type city name here"
                            onChange={e => this.updateLocation(e)} />
                    </div>
                </div>

                <div className="field">
                    <div className="control">
                        <input
                            type='submit'
                            value='Search' />
                    </div>
                </div>
            </form>
        )
    }
}

export default WeatherForm

and I got error: POST http://localhost:4000/weather 404 (Not Found)

2
  • On the update location, you have to create a function that calls the API endpoint. Inside the function, then you update the state. Commented Jul 23, 2020 at 14:44
  • What you want to do is in your express backend, handle the post request coming in at the /weather route, get the location data from the request body, send a post request to the weather api with the location data as the url parameters, wait for the response, and send that in the response to the initial request coming in from your react frontend. That'll then give you the data that you send back as the response to your axios request as part of the resobject that you receive in your .then call in react Commented Jul 23, 2020 at 15:24

1 Answer 1

1

You want to use http requests to send the data to your backend. You can either use the native window.fetch API to send the data via a post request, or you can use a third-party library (I recommend axios).

The recommended way to send a post request on form submit in react is to store the field data in state (use the onChange prop on the input fields to update the state whenever the input value changes), and then use a handler function that gets fired when the submit button is clicked (use the onClick prop for your button element).

The handler function should get the current state (the form input field data) and pass it into the post request as the body.

When your express API receives the request, it can parse the data, and then fire off it's own API request to the openWeather API with that data as the url parameters.

UPDATE:

Updating due to updated question. You don't have a post route defined in your express API. Therefore it won't accept post requests at the /weather route. What you need to do is write a handler that accepts post requests:


app.post('/weather', (req, res, next) => {
  let { country, city } = req.body.data;

  // here you send a post request to the weather API url
  // to retrieve the results, then send them back
  // to your react app to display them
}
Sign up to request clarification or add additional context in comments.

3 Comments

Please see updated question, I'm not sure how to "pass it into the post request as the body"
I've left a comment under your question, hope it helps!
Thank you it helped me to understand the theory, but I'm still not sure about what you said in the code comment. In the React WeatherForm component handleSubmit method am I using Axios.post() to post the location to backend?

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.