DEV Community

Xiaohan Du
Xiaohan Du

Posted on

Let’s build a full stack UK weather app using Node + React: part 2 — error handling

Original post on Medium see here, code example in this article can be found in my Github Page.

Alt Text

In Part 1 we scaffolded a basic set up for our UK weather app and successfully fetched and displayed the weather data from Openweathermap API. An important point in part 1 was how user input data was stored in React state and sent to Node. You may have noticed that some errors happened when non-standard UK postcode was entered, thus in part 2 I’m going to show you my thoughts of handling these errors.

The error

Let’s take a look at what happens if entering a random postcode in the input field: aa123aa

Error without handling

The error is pretty much self-explanatory: response.result = undefined. Console.log(response) and we can see:

response

Openweathermap API returned a 404 error when a false postcode was entered.

How to handle the error?

Two possible issues could cause the error:

  1. The input postcode did not conform to UK format, e.g. qwerty;
  2. The input postcode conformed to UK format, but was not a valid UK postcode, e.g. aa123aa.

For 1, I’m going to add input validation using regex, for 2, I think there is no easy way to prevent a user from entering such postcode, so I’ll handle the error in getCoord method before the address information is fetched.

1. Input validation using regex

When clicking the Search button, handleSubmit method is called which also invokes getCoord method. I add an error state to store the validation status:

if(error === true) {
  // show error message
}
else {
  // remove error message
}

A very simple reminder message is placed next to he input field. In handleSubmit method, the input is validated as follows: if valid, execute getCoord and set error state to false; else set error state to true. The error message should be shown when error === true, and hide when error === false. Let take a look at Weather.js:

You may have noticed that here in handleInputChange method the error state is set to false. This is because if postcode is entered again, a user may already have noticed that he/she entered the wrong postcode, therefore the error message is removed immediately when the input state is changed (we don’t want to over-remind the user). Okay, so now the problem is how can we determine whether input is valid and run getCoord? We could try to add some regex in handleValidation method to address it.

Most UK postcodes follow a certain format thus implementing a regex myself to cover popular cases is possible, but if I want to cover all possible cases, doing it myself becomes infeasible quickly. I found a good solution in this popular Stack overflow answer, so the following code is added to handleValidation method:

handleValidation() {
    let regexConst = new RegExp('^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$');
    return regexConst.test(this.state.postcodeInput);
}

As you can see, the regex pattern is very long, so I didn’t want to spend too much time on it and borrowed the Stack overflow answer. Let’s test it:

Test input validation

Good, now issue 1 is resolved. Issue 2 still persists: that is, if the input conforms UK postcode format and bypasses the regex, how can we handle the error?

2. Try {fetch API} catch {error}

From the console error we can see that the postcode API returned a 404 error, i.e. postcode not found. A simple try… catch statement can be used to catch the error and show the error message. The getCoord method is updated as follows:

async getCoord() {
  const postcodeAPI =   `http://api.postcodes.io/postcodes/${this.state.postcodeInput}`;
  let response;
  try {
    response = await fetch(postcodeAPI);
    if (!response.ok) throw new Error('Weather api request failed.');
    await response.json().then(response => {
      this.setState({
        addressData: response,
        coordinate: [response.result.latitude, response.result.longitude]
      });
      let coord = {
        latitude: this.state.coordinate[0],
        longitude: this.state.coordinate[1]
      }
      axios.post('http://localhost:4001/search-location', coord)
        .then((response) => {
          console.log(response);
          this.setState({
            displayResult: true
          });
        }, (error) => {
          console.log(error);
        });
    });
  }
  catch(e) {
    this.setState({error: true});
    console.log(e);
  }
}

If an invalid postcode is passed to the API, the response object would contain a property ok = false. Therefore this line is added: if (!response.ok) throw new Error(‘Weather api request failed.’); to immediately cease the try statement and catch the error. In the catch statement the error state is set to true such that the little reminder is shown next to the input field. Then the error is logged to the console with text ‘Weather api request failed’. No console error would be shown to the user. Let’s test it:

validation with try...catch

The 404 error in the console is default browser behaviour, so no need to worry about that. The try…catch statement threw the error and logged the message in the console, and the error state made sure that the reminder was displayed.

What’s next?

Now that the errors are handled, one step closer to a good UK weather app. Obviously the app could look a bit prettier, so in the next article I will get the app decorated and show you how to do it.
Hope it helps! 😁

Top comments (1)

Collapse
 
drukey profile image
Drukey

Hi thanks, such a great tutorial. What if I need to display the current weather of other cities, like not based on my current location but for other cities