<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Xiaohan Du</title>
    <description>The latest articles on DEV Community by Xiaohan Du (@xiaohan_du).</description>
    <link>https://dev.to/xiaohan_du</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F358585%2F6794f103-7dec-4e7f-9f8b-be3161389e85.jpg</url>
      <title>DEV Community: Xiaohan Du</title>
      <link>https://dev.to/xiaohan_du</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xiaohan_du"/>
    <language>en</language>
    <item>
      <title>Improve SCSS structure</title>
      <dc:creator>Xiaohan Du</dc:creator>
      <pubDate>Sun, 23 Aug 2020 10:10:41 +0000</pubDate>
      <link>https://dev.to/xiaohan_du/improve-scss-structure-49of</link>
      <guid>https://dev.to/xiaohan_du/improve-scss-structure-49of</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcj36uj75motkzzefmkw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcj36uj75motkzzefmkw5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  A bad example
&lt;/h1&gt;

&lt;p&gt;An example SCSS which is structured as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.widget {
    background-color: red;
    .widget-body {
        background-color: black;
        .widget-link-block {
            background-color: yellow;
            .widget-link-block-menu {
                background-color: green;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which compiles to CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.widget {
    background-color: red;
}

.widget .widget-body {
    background-color: black;
}

.widget .widget-body .widget-link-block {
    background-color: yellow;
}

.widget .widget-body .widget-link-block .widget-link-block-menu {
    background-color: green;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has 2 disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we are repeating keywords like 'widget'&lt;/li&gt;
&lt;li&gt;the compiled CSS relies on HTML structure, i.e. it only works on the following HTML:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget'&amp;gt;
  &amp;lt;div class='widget-body'&amp;gt;
    &amp;lt;div class='widget-link-block'&amp;gt;
      &amp;lt;div class='widget-link-block-menu'&amp;gt;

      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Violating the hierarchy would cause them stop working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget-body'&amp;gt;
&amp;lt;div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not work&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget'&amp;gt;
  &amp;lt;div class='widget-body'&amp;gt;
    &amp;lt;div class='widget-link-block-menu'&amp;gt;
      &amp;lt;div class='widget-link-block'&amp;gt;

      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not work&lt;/p&gt;

&lt;h1&gt;
  
  
  Suggested method
&lt;/h1&gt;

&lt;p&gt;Use SCSS properly and Follow &lt;a href="https://en.bem.info/methodology/" rel="noopener noreferrer"&gt;BEM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above SCSS example can be modified to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.widget {
    background-color: red;
    &amp;amp;-body {
        background-color: black;
    }
    &amp;amp;__link {
        &amp;amp;__block {
            background-color: yellow;
            &amp;amp;__menu {
                background-color: green;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which compiles to CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.widget {
    background-color: red;
}

.widget-body {
    background-color: black;
}

.widget__link__block {
    background-color: yellow;
}

.widget__link__block__menu {
    background-color: green;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the compiled CSS is more compact, less complex. When write SCSS, we no longer repeat writing '.widget'. More importantly, the compiled CSS no longer relies on HTML structure, it can be used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget'&amp;gt;
  &amp;lt;div class='widget-body'&amp;gt;
    &amp;lt;div class='widget__link__block'&amp;gt;
      &amp;lt;div class='widget__link__block__menu'&amp;gt;

      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or in different order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget'&amp;gt;
  &amp;lt;div class='widget-body'&amp;gt;
    &amp;lt;div class='widget__link__block__menu'&amp;gt;
      &amp;lt;div class='widget__link__block'&amp;gt;

      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class='widget-body'&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Let’s build a full stack UK weather app using Node + React: part 2 — error handling</title>
      <dc:creator>Xiaohan Du</dc:creator>
      <pubDate>Mon, 10 Aug 2020 13:23:03 +0000</pubDate>
      <link>https://dev.to/xiaohan_du/let-s-build-a-full-stack-uk-weather-app-using-node-react-part-2-error-handling-11gj</link>
      <guid>https://dev.to/xiaohan_du/let-s-build-a-full-stack-uk-weather-app-using-node-react-part-2-error-handling-11gj</guid>
      <description>&lt;p&gt;Original post on Medium see &lt;a href="https://medium.com/@duxiaohan_34311/lets-build-a-full-stack-uk-weather-app-using-node-react-part-2-error-handling-96323ca8e3c5"&gt;here&lt;/a&gt;, code example in this article can be found in &lt;a href="https://github.com/xiaohan-du/code-playground/tree/master/full-stack-weather-app"&gt;my Github Page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cOqFsKal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eadmrxp8a87d3wlalfcb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cOqFsKal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eadmrxp8a87d3wlalfcb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/xiaohan_du/let-s-build-a-full-stack-uk-weather-app-using-node-react-part-1-basic-setup-4n1"&gt;Part 1&lt;/a&gt; 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.&lt;/p&gt;

&lt;h1&gt;
  
  
  The error
&lt;/h1&gt;

&lt;p&gt;Let’s take a look at what happens if entering a random postcode in the input field: aa123aa&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vu8nMABy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ulv1u605ybma2gn92rch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vu8nMABy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ulv1u605ybma2gn92rch.png" alt="Error without handling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The error is pretty much self-explanatory: &lt;code&gt;response.result = undefined&lt;/code&gt;. &lt;code&gt;Console.log(response)&lt;/code&gt; and we can see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PzZanSl---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/syr24q60obyjztboe1vm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PzZanSl---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/syr24q60obyjztboe1vm.png" alt="response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Openweathermap API returned a 404 error when a false postcode was entered.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to handle the error?
&lt;/h1&gt;

&lt;p&gt;Two possible issues could cause the error:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The input postcode did not conform to UK format, e.g. qwerty;&lt;/li&gt;
&lt;li&gt;The input postcode conformed to UK format, but was not a valid UK postcode, e.g. aa123aa.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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 &lt;code&gt;getCoord&lt;/code&gt; method before the address information is fetched.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Input validation using regex
&lt;/h2&gt;

&lt;p&gt;When clicking the Search button, &lt;code&gt;handleSubmit&lt;/code&gt; method is called which also invokes &lt;code&gt;getCoord&lt;/code&gt; method. I add an &lt;code&gt;error&lt;/code&gt; state to store the validation status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(error === true) {
  // show error message
}
else {
  // remove error message
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


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


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;You may have noticed that here in &lt;code&gt;handleInputChange&lt;/code&gt; method the &lt;code&gt;error&lt;/code&gt; state is set to &lt;code&gt;false&lt;/code&gt;. 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 &lt;code&gt;getCoord&lt;/code&gt;? We could try to add some regex in &lt;code&gt;handleValidation&lt;/code&gt; method to address it.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://stackoverflow.com/questions/164979/regex-for-matching-uk-postcodes"&gt;this popular Stack overflow answer&lt;/a&gt;, so the following code is added to &lt;code&gt;handleValidation&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ukfXuSjS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h4nort32yku4lytk6uuk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ukfXuSjS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h4nort32yku4lytk6uuk.gif" alt="Test input validation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Try {fetch API} catch {error}
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;getCoord&lt;/code&gt; method is updated as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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 =&amp;gt; {
      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) =&amp;gt; {
          console.log(response);
          this.setState({
            displayResult: true
          });
        }, (error) =&amp;gt; {
          console.log(error);
        });
    });
  }
  catch(e) {
    this.setState({error: true});
    console.log(e);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If an invalid postcode is passed to the API, the response object would contain a property &lt;code&gt;ok = false&lt;/code&gt;. Therefore this line is added: &lt;code&gt;if (!response.ok) throw new Error(‘Weather api request failed.’);&lt;/code&gt; to immediately cease the try statement and catch the error. In the &lt;code&gt;catch&lt;/code&gt; statement the &lt;code&gt;error&lt;/code&gt; state is set to &lt;code&gt;true&lt;/code&gt; 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:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zgFn9gF7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z9mbrihwcfl5939wmcrm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zgFn9gF7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z9mbrihwcfl5939wmcrm.gif" alt="validation with try...catch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;error&lt;/code&gt; state made sure that the reminder was displayed.&lt;/p&gt;

&lt;h1&gt;
  
  
  What’s next?
&lt;/h1&gt;

&lt;p&gt;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.&lt;br&gt;
Hope it helps! 😁&lt;/p&gt;

</description>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Let’s build a full stack UK weather app using Node + React: part 1 — basic setup</title>
      <dc:creator>Xiaohan Du</dc:creator>
      <pubDate>Wed, 05 Aug 2020 22:15:31 +0000</pubDate>
      <link>https://dev.to/xiaohan_du/let-s-build-a-full-stack-uk-weather-app-using-node-react-part-1-basic-setup-4n1</link>
      <guid>https://dev.to/xiaohan_du/let-s-build-a-full-stack-uk-weather-app-using-node-react-part-1-basic-setup-4n1</guid>
      <description>&lt;p&gt;Original post on Medium see &lt;a href="https://medium.com/@duxiaohan_34311/lets-build-a-full-stack-uk-weather-app-using-node-react-part-1-basic-set-up-8b58534afa7b"&gt;here&lt;/a&gt;, code example see &lt;a href="https://github.com/xiaohan-du/code-playground/tree/master/full-stack-weather-app"&gt;my Github page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The easy way: look up in the sky&lt;/li&gt;
&lt;li&gt;The intermediate choice: use &lt;a href="https://www.bbc.co.uk/weather"&gt;BBC weather&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;The hard mode: build you own weather app!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article I will demo the hard mode here, yeah, why not ✌️.&lt;/p&gt;

&lt;p&gt;The app is built using &lt;a href="https://reactjs.org/"&gt;React JS&lt;/a&gt; as frontend and &lt;a href="https://nodejs.org/en/"&gt;Node JS&lt;/a&gt; as backend. It also involves fetching weather data from &lt;a href="https://openweathermap.org/api"&gt;Openweathermap API&lt;/a&gt; and UK geological data from &lt;a href="https://postcodes.io/"&gt;Postcodes.io&lt;/a&gt;, so make sure you have both API ready. FYI Openweathermap API requires an API key and Postcodes.io does not.&lt;/p&gt;

&lt;h1&gt;
  
  
  Basic idea
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RNaQnFrv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f42ygkhjw7uwim0o6rev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RNaQnFrv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f42ygkhjw7uwim0o6rev.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a React component &lt;code&gt;Weather.js&lt;/code&gt; contains a form element which allows user to input UK postcode. &lt;code&gt;Weather.js&lt;/code&gt; should also contain a sub component &lt;code&gt;WeatherResult.js&lt;/code&gt; which is only rendered when weather data is successfully fetched.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Weather.js&lt;/code&gt; 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.&lt;/li&gt;
&lt;li&gt;The Openweathermap API receives these coordinates. Node then gets the response and sends it back to &lt;code&gt;WeatherResult.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WeatherResult.js&lt;/code&gt; 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):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;full-stack-weather-app
├── backend
│ ├── index.js
.
.
.
├── frontend
│ ├── public
│ ├── src
│ │ ├── components
│ │ │ ├── Weather.js
│ │ │ ├── WeatherResult.js
│ ├── App.css
│ ├── App.js
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;where &lt;code&gt;frontend&lt;/code&gt; folder is created via create-react-app: &lt;code&gt;npx create-react-app frontend&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Frontend: set up &lt;code&gt;Weather.js&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;We are going to render the application from &lt;code&gt;App.js&lt;/code&gt;, so change default &lt;code&gt;App.js&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;we could see that only &lt;code&gt;Weather.js&lt;/code&gt; component is rendered. Let’s take a look at it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;p&gt;As user inputs postcode, the &lt;code&gt;onChange&lt;/code&gt; event in form &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element picks up the use input and invokes the handleInputChange method. &lt;code&gt;postcodeInput&lt;/code&gt; state then receives and stores the postcode input. &lt;code&gt;displayResult&lt;/code&gt; state is set to &lt;code&gt;false&lt;/code&gt; such that when user inputs changes, &lt;code&gt;weatherResult&lt;/code&gt; component is hidden (see the demo at the end).&lt;/p&gt;

&lt;p&gt;Now let’s take a look at &lt;code&gt;getCoord&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;h1&gt;
  
  
  Backend: wrap all in &lt;code&gt;index.js&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;For backend, we will only have an &lt;code&gt;index.js&lt;/code&gt; file for all functionalities. Let’s take a look at the file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt; does 3 jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;line 8–19: set the application to listen on port 4001,&lt;/li&gt;
&lt;li&gt;line 21–38: send a post request to &lt;code&gt;http://localhost:4001/search-location&lt;/code&gt; to obtain coordinates,&lt;/li&gt;
&lt;li&gt;line 40–49: send a get request to &lt;code&gt;http://localhost:4001/weather&lt;/code&gt; so the endpoint could receive the weather data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far you might ask a question: &lt;strong&gt;Why do we have to pass &lt;code&gt;coord&lt;/code&gt; to Node?&lt;/strong&gt; Wouldn’t it be easier to fetch weather data in React immediately follows user input?&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How did we do it?&lt;/strong&gt; Remember in &lt;code&gt;getCoord&lt;/code&gt; method we used an &lt;code&gt;axios.post&lt;/code&gt; method to post object &lt;code&gt;coord&lt;/code&gt; to &lt;code&gt;http://localhost:4001/search-location&lt;/code&gt;? Here in &lt;code&gt;index.js&lt;/code&gt; we fetch &lt;code&gt;coord&lt;/code&gt; 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 &lt;a href="https://medium.com/swlh/hide-api-key-in-node-application-and-request-it-from-react-application-175ce257f493"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Frontend: display weather in &lt;code&gt;WeatherResult.js&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;On line 40 of &lt;code&gt;index.js&lt;/code&gt;, the weather data has been sent to &lt;code&gt;http://localhost:4001/weather&lt;/code&gt;, thus in &lt;code&gt;WeatherResult.js&lt;/code&gt; we fetch weather data and display it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O4YsSuNx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b3wmz9s4wfvjrt8lunfg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O4YsSuNx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b3wmz9s4wfvjrt8lunfg.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works!&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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. 😁&lt;/p&gt;

</description>
      <category>react</category>
      <category>node</category>
    </item>
  </channel>
</rss>
