DEV Community

Xiaohan Du
Xiaohan Du

Posted on

Let’s build a full stack UK weather app using Node + React: part 1 — basic setup

Original post on Medium see here, code example see my Github page

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
  • 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 as frontend and Node JS as backend. It also involves fetching weather data from Openweathermap API and UK geological data from 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

  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:

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

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:

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:

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.

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:

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

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. 😁

Top comments (0)