Hey fellow developers!
This post is about how to create a simple weather app using React and OpenWeatherMap API.
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 and live demo here
Now let's divide this into a few steps,
- Setup a React app using Create-React-App
- Get the API Key from OpenWeatherMap API
- 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.
npx create-react-app react-weather-app
Like in the image shown below.
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
Let's move to next step π
Step - 2
- Goto OpenWeatherMap website here
- Create a new account
- Login to that account
- Click on My API Key section
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.
Create a file called .env
in our project's root folder.
Open that file and create a new variable named REACT_APP_API_KEY
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()
// 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.
- apiData state is used to store the response
- getState is used to store the location name from input field
- 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.
// 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.
// 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.
const inputHandler = (event) => {
setGetState(event.target.value);
};
const submitHandler = () => {
setState(getState);
};
const kelvinToFarenheit = (k) => {
return (k - 273.15).toFixed(2);
};
- inputHandler this function is used to handle the input field, to get the data and store in getState.
- submitHandler this function is used to copy the state from getState to state.
- 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,
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)}° 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)}° C
</strong>
</p>
<p>
<i className="fas fa-temperature-high"></i>{' '}
<strong>
{kelvinToFarenheit(apiData.main.temp_max)}° 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.
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!π
Top comments (0)