A Simple Weather app using React and OpenWeatherMap API 🔥
Tags: react, javascript, api, bootstrap
Published: 2020-12-13 02:41:42

Hey fellow developers!
This post is about how to create a simple weather app using React and OpenWeatherMap API.

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

This is how the app will look like.
So, let's get started 🏃‍♂️

> Here's the github link in case you're curious [react-weather-app](https://github.com/imshines/react-weather-app) and live demo [here](https://react-weather-app-beta.vercel.app/)

Now let's divide this into a few steps,

1. Setup a React app using Create-React-App
2. Get the API Key from OpenWeatherMap API
3. Code, code, code! 👨‍💻

### Step - 1

If you're already familiar with create-react-app skip this step and set-up a project or if you're new follow along.

* Open up a terminal or command prompt in your preferred folder and enter the following command.

```javascript
npx create-react-app react-weather-app
```

Like in the image shown below.

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

After that, navigate to that folder by entering
```
cd react-weather-app
```
And then start the project using the following command
```
npm start
```

for more details on create-react-app check [here](https://create-react-app.dev/docs/getting-started/)

Let's move to next step 😀

### Step - 2

1. Goto OpenWeatherMap website [here](https://openweathermap.org/)
2. Create a new account
3. Login to that account
4. Click on **My API Key** section

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

Now you can find the API key, if it is not present. Then generate a new API key.

After that copy the API Key (Don't share your API Key publicly).

### Step - 3

First we'll store the generated API key in our project.

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

Create a file called `.env` in our project's root folder.
Open that file and create a new variable named `REACT_APP_API_KEY`

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

It should look like the image as shown above.
That's it for the API key store.

I have used bootstrap, this is totally optional, you can add via cdn or install as an npm package.

#### Modifying App.js file

Open your App.js file and enter the code as follows,
Add these variables before your return()
```javascript
// API KEY AND URL
const apiKey = process.env.REACT_APP_API_KEY;
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${state}&appid=${apiKey}`;
```

#### Now let's create some states to store the API data and input.
1. apiData state is used to store the response
2. getState is used to store the location name from input field
3. state is used to store a copy of the getState this will be helpful in updating state on button click. You can ignore this state and directly pass getState on the URL as well.
```javascript
// State
const [apiData, setApiData] = useState({});
const [getState, setGetState] = useState('tamilnadu');
const [state, setState] = useState('tamilnadu');

// API KEY AND URL
const apiKey = process.env.REACT_APP_API_KEY;
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${state}&appid=${apiKey}`;
```
#### Now let's make an api request using fetch and useEffect Hook.
```javascript
// Side effect
useEffect(() => {
  fetch(apiUrl)
    .then((res) => res.json())
    .then((data) => setApiData(data));
}, [apiUrl]);
```
The useEffect hook is used to perform side effects on your app, this is an alternative to componentDidMount, unmount, etc.. lifecycle hook from react class components.

What this does is, it fetches the data from the given api url and stores in apiData state. This happens only when apiUrl changes thus it will prevent unwanted re-render. [] this is the dependency array this determines when to re-render a componenet, when it is left empty it'll render only once. When we specify a dependency it will render only when it is updated.

#### Next we'll write some functions to handle the input.
```javascript
const inputHandler = (event) => {
  setGetState(event.target.value);
};

const submitHandler = () => {
  setState(getState);
};

const kelvinToFarenheit = (k) => {
  return (k - 273.15).toFixed(2);
};
```
1. inputHandler this function is used to handle the input field, to get the data and store in getState.
2. submitHandler this function is used to copy the state from getState to state.
3. kelvinToFarenheit this function is used to convert kelvin to farenheit, since we get the data from api as kelvin we're using this function.

#### Finally write this code in your return statement,
```javascript
return (
  <div className="App">
    <header className="d-flex justify-content-center align-items-center">
      <h2>React Weather App</h2>
    </header>
    <div className="container">
      <div className="mt-3 d-flex flex-column justify-content-center align-items-center">
        <div class="col-auto">
          <label for="location-name" class="col-form-label">
            Enter Location :
          </label>
        </div>
        <div class="col-auto">
          <input
            type="text"
            id="location-name"
            class="form-control"
            onChange={inputHandler}
            value={getState}
          />
        </div>
        <button className="btn btn-primary mt-2" onClick={submitHandler}>
          Search
        </button>
      </div>

      <div className="card mt-3 mx-auto" style={{ width: '60vw' }}>
        {apiData.main ? (
          <div class="card-body text-center">
            <img
              src={`http://openweathermap.org/img/w/${apiData.weather[0].icon}.png`}
              alt="weather status icon"
              className="weather-icon"
            />

            <p className="h2">
              {kelvinToFarenheit(apiData.main.temp)}&deg; C
            </p>

            <p className="h5">
              <i className="fas fa-map-marker-alt"></i>{' '}
              <strong>{apiData.name}</strong>
            </p>

            <div className="row mt-4">
              <div className="col-md-6">
                <p>
                  <i class="fas fa-temperature-low "></i>{' '}
                  <strong>
                    {kelvinToFarenheit(apiData.main.temp_min)}&deg; C
                  </strong>
                </p>
                <p>
                  <i className="fas fa-temperature-high"></i>{' '}
                  <strong>
                    {kelvinToFarenheit(apiData.main.temp_max)}&deg; C
                  </strong>
                </p>
              </div>
              <div className="col-md-6">
                <p>
                  {' '}
                  <strong>{apiData.weather[0].main}</strong>
                </p>
                <p>
                  <strong>
                    {' '}
                    {countries.getName(apiData.sys.country, 'en', {
                      select: 'official',
                    })}
                  </strong>
                </p>
              </div>
            </div>
          </div>
        ) : (
          <h1>Loading</h1>
        )}
      </div>
    </div>
    <footer className="footer">
      <code>
        Created by{' '}
        <a href="https://github.com/imshines" target="none">
          imshines
        </a>{' '}
        using React
      </code>
    </footer>
  </div>
);
```

I have used bootstrap for styling it's totally optional, the rest of the code is pretty self explanatory. We're just displaying the data from the apiData state object by accessing it's keys.

![Alt text](https://media1.tenor.com/images/d5bac75176f31335f0849b9a0284b2aa/tenor.gif?itemid=8344269)

#### Completed!

That's pretty much it, we have successfully completed the app, this app will show you weather of the state that you enter in the input field.

This is my first blog post kindly let me know your thoughts on this in the comment section below. I'm not a professional Reactjs developer so, let me know if there's any unwanted code present in it. 😁

Thanks for reading, hope you enjoyed 👍
Will see you again in the next one, bye!👋