Create a weather Application using React Redux
Weather App is a web application designed to provide real-time weather information for any location worldwide. In this article, we will make a Weather App using React and Redux. It offers a seamless and intuitive user experience, allowing users to easily access accurate weather forecasts ( temperature, wind speed, humidity etc.) by just entering any city name.
Project preview:
Prerequisites:
- Nodejs
- React and Axios
- Redux and React-Redux
Approach
- React App & dependencies : Use Create React App to set up a new React project named weather-app and install Redux, React Redux and Axios.
- Redux Setup : Create a store.js file to set up the Redux store, define required reducers and actions and use createStore method to create store.
- Weather API : Select a weather API platform, create an account, and integrate its keys and endpoint into your React app.
- Component : Implement weather display, location input, loading indicator, and error message in the weather app and also integrating Redux state and actions.
Steps to Create React Application
Step 1: Create React Application named weather-app and navigate to it using this command.
npx create-react-app weather-app
cd weather-app
Step 2: Install required packages and dependencies.
npm install react-redux redux axios
Updated dependencies in package.json file
Installed dependencies will look like the below file in package.json file.
"dependencies": {
"axios": "^1.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.1",
"redux": "^5.0.1"
},
File structure:
Example:
/* App.css */
#App-wrapper {
/* text-align: center; */
justify-content: center;
display: flex;
}
#app {
text-align: center;
width: 500px;
display: flex;
flex-direction: column;
}
#head {
display: flex;
gap: 10px;
align-items: center;
}
input {
padding: 10px 20px;
border: 1px solid black;
margin: 5px;
}
button {
padding: 10px 20px;
border: 1px solid black;
/* margin: 5px; */
cursor: pointer;
background-color: rgb(230, 230, 230);
}
button:hover {
background-color: rgba(9, 204, 9, 0.61);
}
p {
background-color: rgb(230, 230, 230);
padding: 10px 20px;
margin: 5px 0px;
text-transform: capitalize;
}
p span {
color: green;
}
// store.js
import { createStore, combineReducers } from "redux";
// actions
export const fetchWeatherRequest = () => ({
type: "FETCH_WEATHER_REQUEST",
});
export const fetchWeatherSuccess = (data) => ({
type: "FETCH_WEATHER_SUCCESS",
payload: data,
});
export const fetchWeatherFailure = (error) => ({
type: "FETCH_WEATHER_FAILURE",
payload: error,
});
// reducers/weatherReducer.js
const initialState = {
weatherData: null,
loading: false,
error: null,
};
const weatherReducer = (state = initialState, action) => {
switch (action.type) {
case "FETCH_WEATHER_REQUEST":
return {
...state,
loading: true,
error: null,
};
case "FETCH_WEATHER_SUCCESS":
return {
...state,
loading: false,
weatherData: action.payload,
};
case "FETCH_WEATHER_FAILURE":
return {
...state,
loading: false,
error: action.payload,
};
default:
return state;
}
};
// store.js
const rootReducer = combineReducers({
weather: weatherReducer,
// Add more reducers if needed
});
const store = createStore(rootReducer);
export default store;
// App.js
import React, { useState } from "react";
import axios from "axios";
import { connect } from "react-redux";
import {
fetchWeatherRequest,
fetchWeatherSuccess,
fetchWeatherFailure,
} from "./store";
import "./App.css";
const WeatherApp = ({ weatherData, loading, error, fetchWeather }) => {
const [city, setCity] = useState("");
const findHandle = async () => {
await fetchWeather(city);
};
console.log(weatherData);
return (
<div id="App-wrapper">
<div id="app">
<div id="head">
<img
src="https://media.w3wiki.net/gfg-gg-logo.svg"
alt="gfg_logo"
/>
<label>Enter City Name</label>
<input
type="text"
value={city}
onChange={(e) => setCity(e.target.value)}
/>
<button onClick={findHandle}>Find</button>
</div>
<div>
{loading && <p>Loading...</p>}
{error && <p>Error: {error}</p>}
{weatherData && (
<div>
<div>
<img src={weatherData?.current?.condition.icon} />
<p>{weatherData?.current?.condition.text}</p>
</div>
<div>
<p>
Temperature : <span>{weatherData?.current?.temp_c}c</span>
</p>
<p>
Humidity : <span>{weatherData?.current?.humidity}</span>
</p>
<p>
Wind Speed : <span>{weatherData?.current.wind_kph}kph</span>
</p>
</div>
<div>
{Object.keys(weatherData?.location).map((key) => (
<p key={key}>
{key} : <span>{weatherData.location[key]}</span>
</p>
))}
</div>
</div>
)}
</div>
</div>
</div>
);
};
const mapStateToProps = (state) => ({
weatherData: state.weather.weatherData,
loading: state.weather.loading,
error: state.weather.error,
});
const mapDispatchToProps = (dispatch) => ({
fetchWeather: (city) => {
dispatch(fetchWeatherRequest());
fetchWeatherData(city)
.then((data) => dispatch(fetchWeatherSuccess(data)))
.catch((err) => dispatch(fetchWeatherFailure(err.message)));
},
});
// feathermatch function
async function fetchWeatherData(city = "Delhi") {
const API_KEY = "XXXXX-XXXXX-XXXXX";
const response = await axios.get(
`https://api.weatherapi.com/v1/current.json?q=${city}&key=${API_KEY}`
);
console.log(response);
if (response.status != 200) {
throw new Error("Failed to fetch weather data");
}
return response.data;
}
export default connect(mapStateToProps, mapDispatchToProps)(WeatherApp);
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
Command to Run Weather Application:
To run weather application open your terminal and navigate to weather-app directory and enter the following command.
npm start
Output:
Contact Us