Let’s build a full stack UK weather app using Node + React: part 1 — basic setup
Tags: react, node
Published: 2020-08-05 22:15:31

Original post on Medium see [here](https://medium.com/@duxiaohan_34311/lets-build-a-full-stack-uk-weather-app-using-node-react-part-1-basic-set-up-8b58534afa7b), code example see [my Github page](https://github.com/xiaohan-du/code-playground/tree/master/full-stack-weather-app)

UK weather isn’t that great, if you want to be prepared and find out what weather is like in the UK, you may have 3 choices:
* The easy way: look up in the sky
* The intermediate choice: use [BBC weather](https://www.bbc.co.uk/weather) 
* The hard mode: build you own weather app!

In this article I will demo the hard mode here, yeah, why not ✌️.

The app is built using [React JS](https://reactjs.org/) as frontend and [Node JS](https://nodejs.org/en/) as backend. It also involves fetching weather data from [Openweathermap API](https://openweathermap.org/api) and UK geological data from [Postcodes.io](https://postcodes.io/), so make sure you have both API ready. FYI Openweathermap API requires an API key and Postcodes.io does not.

# Basic idea

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f42ygkhjw7uwim0o6rev.png)

1. Add a React component `Weather.js` contains a form element which allows user to input UK postcode. `Weather.js` should also contain a sub component `WeatherResult.js` which is only rendered when weather data is successfully fetched.
2. `Weather.js` passes the input postcode to Postcodes API and get the geological coordinates. The coordinates are then sent to Openweathermap API in the backend. The reason of sending coordinates rather than directly sending postcode to Openweathermap API is: we will be able to save the effort of regulating the user input to meet Openweathermap API requirements.
3. The Openweathermap API receives these coordinates. Node then gets the response and sends it back to `WeatherResult.js`.
4. `WeatherResult.js` renders the data and presents to the user.
# File structure
The main file structure is as follows (some less important files are ignored, such as node_modules):
```
full-stack-weather-app
├── backend
│ ├── index.js
.
.
.
├── frontend
│ ├── public
│ ├── src
│ │ ├── components
│ │ │ ├── Weather.js
│ │ │ ├── WeatherResult.js
│ ├── App.css
│ ├── App.js
.
.
.
```
where `frontend` folder is created via create-react-app: `npx create-react-app frontend`.
# Frontend: set up `Weather.js`
We are going to render the application from `App.js`, so change default `App.js` to:
{% gist https://gist.github.com/xiaohan-du/6320bae09bf962092e79e60b1cf82090 %}

we could see that only `Weather.js` component is rendered. Let’s take a look at it:

{% gist https://gist.github.com/xiaohan-du/ed5a0f8304cf2706778ed8b270af1ebd %}

`Weather.js` is quite long so we will take a look at `getCoord` method separately. Also let’s not worry about the CSS classes in the `render` method for the time being. Currently the component renders a plain form with no styling. There are several states: `addressData` is used to store the complete address data fetched from Postcodes API, coordinates are then extracted and stored in `coordinate` state. `postcodeInput` is used to store the input postcode when form input updates. Finally `displayResult` is a Boolean value which renders/hides `WeatherResult` component.

As user inputs postcode, the `onChange` event in form `<input>` element picks up the use input and invokes the handleInputChange method. `postcodeInput` state then receives and stores the postcode input. `displayResult` state is set to `false` such that when user inputs changes, `weatherResult` component is hidden (see the demo at the end).

Now let’s take a look at `getCoord` method:
{% gist https://gist.github.com/xiaohan-du/3c567d5eb7133011e3cc6486bf517f19 %}

The Postcodes API is open source and does not require an API key to use, thus we could directly use it in `Weather.js`. Variable `postcodeAPI` receives the postcode input and completes the API. Weather data is then fetched and coordinates are passed into `coordinate` state. A post request is sent to `http://localhost:4001/search-location`, here we specify the full endpoint, otherwise if using `/search-location` only, the post request would be sent to `http://localhost:3000/search-location`. Meanwhile we set state `displayResult` to true, such that the `weatherResult` component will only be rendered if a response is returned successfully.

# Backend: wrap all in `index.js`
For backend, we will only have an `index.js` file for all functionalities. Let’s take a look at the file:
{% gist https://gist.github.com/xiaohan-du/7da7c0931b7d79d75294a25fc42b0661 %}

A global variable `apiUrl` is defined here to store the Openweathermap API, which follows the format: `http://api.openweathermap.org/data/2.5/weather?lat=123&lon=321&appid=12345qwerty`.

`index.js` does 3 jobs:

1. line 8–19: set the application to listen on port 4001,
2. line 21–38: send a post request to `http://localhost:4001/search-location` to obtain coordinates,
3. line 40–49: send a get request to `http://localhost:4001/weather` so the endpoint could receive the weather data.

So far you might ask a question: **Why do we have to pass `coord` to Node?** Wouldn’t it be easier to fetch weather data in React immediately follows user input?

The reason is that an API key should never be stored in frontend as it might be exposed to users through DevTools. As a result, user input needs to be passed to Node.

**How did we do it?** Remember in `getCoord` method we used an `axios.post` method to post object `coord` to `http://localhost:4001/search-location`? Here in `index.js` we fetch `coord` from it and insert into the Openweathermap API. Plus the API key is stored in .env file and never pushed to version control, so the potential issue of exposing API key to users is eliminated. For securely store API key in .env file and fetch it in Node, see my other article [here](https://medium.com/swlh/hide-api-key-in-node-application-and-request-it-from-react-application-175ce257f493).

# Frontend: display weather in `WeatherResult.js`
On line 40 of `index.js`, the weather data has been sent to `http://localhost:4001/weather`, thus in `WeatherResult.js` we fetch weather data and display it as follows:
{% gist https://gist.github.com/xiaohan-du/b942861479b060d1f70c0294aea62506 %}

Recall in `Weather.js` line 56 we conditionally render `WeatherResult` component based on `displayResult` state, and `fetchWeather` method is only called on `componentDidMount`, thus no request is sent if `WeatherResult` component is not mounted. Open a terminal in ./frontend and type `npm start`, we get the React app running. Let’s give it a go:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/b3wmz9s4wfvjrt8lunfg.gif)

It works!

Until now we have scaffolded a full stack weather app using Node as backend and React as front end. For me the most important thing to take home is how to send React state to Node. I think this is fairly useful if your website needs to take a user input and embed it into an API, and this API must be stored in Node.

In part 2 and part 3 we will deal with some error handling and HTML + SCSS to make the app prettier. Thanks for reading, see you later. 😁