Developing a Weather Application Using a REST API
Course: React Native Training
Topic: Developing a Weather Application Using a REST API
Course Link: React Native Training
Demo Link: Register for a Course Demo
JustAcademy Website: Visit JustAcademy
1. Introduction to Weather Application Development
A weather application is a mobile application that displays weather information such as temperature, humidity, wind speed, atmospheric pressure, and weather conditions for a particular location. React Native allows developers to create weather applications for Android and iOS using JavaScript or TypeScript and reusable components.
Weather conditions change continuously, so an application needs to retrieve updated information from a weather service. A REST API makes this possible by allowing the application to send HTTP requests to a remote server and receive structured data in response.
For example, when a user searches for Mumbai, the application sends a request to a weather API. The server processes the request and returns information about Mumbai's weather. The application then displays the returned information using React Native components.
1.1 Main Features of the Application
- Search for weather information by city name.
- Retrieve current weather conditions from a REST API.
- Display temperature in Celsius or Fahrenheit.
- Show humidity, wind speed, and weather descriptions.
- Display a loading indicator while data is being retrieved.
- Handle invalid city names and network errors.
- Refresh weather information when required.
- Provide a responsive and user-friendly interface.
1.2 Learning Objectives
After completing this topic, learners will be able to:
- Understand REST APIs and HTTP communication.
- Configure a weather API provider and obtain an API key.
- Send GET requests from a React Native application.
- Use Fetch, async, and await for asynchronous operations.
- Understand JSON responses and access nested properties.
- Manage weather data using React hooks.
- Build reusable user interface components.
- Implement loading, success, and error states.
- Test API integration and troubleshoot common errors.
- Apply security and performance best practices.
2. Understanding REST APIs
2.1 What Is an API?
API stands for Application Programming Interface. It defines how one software application communicates with another system through a specified interface.
In a weather application, React Native manages the user interface while the weather service provides weather information. The API acts as the communication interface between these systems.
For example, the application requests the current temperature and humidity of a city. The weather server processes the request and returns the required information.
2.2 What Is a REST API?
REST stands for Representational State Transfer. A REST API commonly exposes resources through URLs and uses HTTP methods to retrieve or modify information.
| HTTP Method |
Purpose |
Example |
| GET |
Retrieve information. |
Get the current weather for Mumbai. |
| POST |
Submit information to a server. |
Submit feedback to a backend service. |
| PUT |
Replace a resource. |
Replace a saved user preference. |
| PATCH |
Partially update a resource. |
Update one preference. |
| DELETE |
Delete a resource. |
Remove a saved location from a backend. |
A basic weather application mainly uses GET requests because its primary task is to retrieve weather information rather than modify the provider's data.
2.3 How a Weather API Works
- The user enters a city name.
- The application validates the input.
- The application creates the API request URL.
- The Fetch API sends an HTTP GET request.
- The weather server processes the request.
- The server returns an HTTP response containing weather data.
- The application checks the response status.
- The response body is parsed into JSON.
- The application stores the data in React state.
- The interface updates to display the weather information.
2.4 Weather Application Request Flow
User enters a city
|
v
React Native interface
|
v
Validate city input
|
v
Create API request URL
|
v
Send HTTP GET request
|
v
Weather API server
|
v
Receive JSON response
|
v
Validate and process data
|
v
Update React state
|
v
Display weather information
3. Setting Up the Development Environment
3.1 Prerequisites
Before starting the project, learners should understand basic JavaScript, React components, React Native styling, asynchronous functions, and JSON objects.
3.2 Required Tools
| Tool |
Purpose |
| Node.js |
Provides the JavaScript runtime and development tools. |
| npm |
Installs dependencies and executes project scripts. |
| Expo |
Simplifies React Native project setup and testing. |
| Visual Studio Code |
Provides an editor for writing application code. |
| Android emulator or physical device |
Runs and tests the mobile application. |
| Weather API provider |
Supplies weather information through HTTP requests. |
3.3 Creating a React Native Project
Run the following commands in a terminal to create an Expo-based React Native project.
npx create-expo-app@latest WeatherApp
cd WeatherApp
npx expo start
Open the generated project in your code editor. Depending on the selected template, the main screen may be defined in App.js, App.tsx, or a route file inside an app directory.
4. Selecting and Configuring a Weather API
A weather API provides the current conditions and forecasts that the application displays. Select a provider based on its supported endpoints, data coverage, request limits, pricing, and terms of use.
4.1 Example Weather API Provider
This tutorial uses OpenWeather as an example provider.
Website: OpenWeather
Current weather documentation: Current Weather Data API
4.2 Obtaining an API Key
- Visit the weather provider's official website.
- Create an account or sign in.
- Open the API key or account dashboard section.
- Create or copy an API key according to the provider's instructions.
- Review the endpoint documentation and required parameters.
- Check whether the key is active and permitted to access the selected endpoint.
- Test the request using a development environment.
An API key identifies or authorizes a client when it requests data. An incorrect, inactive, or unauthorized key may cause an authentication error.
4.3 Understanding the API Endpoint
An endpoint is the URL through which an application accesses a particular API resource.
https://api.openweathermap.org/data/2.5/weather
The current weather endpoint accepts query parameters such as the city name, units, and API key.
https://api.openweathermap.org/data/2.5/weather?q=Mumbai&units=metric&appid=YOUR_API_KEY
| Parameter |
Description |
| q |
Specifies the city to search for. |
| units=metric |
Requests metric units, including Celsius for temperature. |
| appid |
Provides the API key required by this endpoint. |
Replace YOUR_API_KEY with your own configured key. Do not publish a real key in public repositories, screenshots, or production source code.
5. Understanding JSON Weather Responses
JSON stands for JavaScript Object Notation. It is a structured text format used to exchange data between applications and servers.
5.1 Example JSON Response
The following response is illustrative. Actual weather values depend on the requested location and the information returned by the provider.
{
"name": "Mumbai",
"main": {
"temp": 29.5,
"feels_like": 33.2,
"humidity": 75,
"pressure": 1008
},
"weather": [
{
"main": "Clouds",
"description": "scattered clouds"
}
],
"wind": {
"speed": 4.1
}
}
5.2 Important JSON Properties
| Property |
Purpose |
Example |
| name |
Location name. |
Mumbai |
| main.temp |
Current temperature. |
29.5 |
| main.feels_like |
Perceived temperature. |
33.2 |
| main.humidity |
Relative humidity percentage. |
75 |
| main.pressure |
Atmospheric pressure. |
1008 hPa |
| weather[0].main |
Short weather category. |
Clouds |
| weather[0].description |
Detailed weather description. |
Scattered clouds |
| wind.speed |
Wind speed in the requested unit system. |
4.1 m/s |
5.3 Accessing Nested Properties
JavaScript dot notation accesses properties inside nested objects, while array indexing accesses elements in arrays.
const temperature = data.main.temp;
const humidity = data.main.humidity;
const city = data.name;
const description = data.weather[0].description;
const windSpeed = data.wind.speed;
Check that expected properties exist before accessing them. Error responses may have a different structure from successful weather responses.
6. Making API Requests with Fetch
The Fetch API allows React Native applications to send HTTP requests. It returns a Promise that resolves to a Response object when the server responds.
6.1 Basic GET Request
async function getWeather() {
const url =
"https://api.openweathermap.org/data/2.5/weather" +
"?q=Mumbai&units=metric&appid=YOUR_API_KEY";
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Weather request failed: ${response.status}`
);
}
const data = await response.json();
return data;
}
6.2 Understanding async and await
- async: Declares a function that returns a Promise.
- await: Waits for an asynchronous operation to settle before continuing inside the async function.
- fetch(): Sends the HTTP request.
- response.ok: Indicates whether the HTTP status is in the successful range.
- response.json(): Reads and parses the response body as JSON.
- try/catch: Handles errors during request processing.
6.3 Why Check response.ok?
Fetch does not automatically throw an exception for every unsuccessful HTTP status. A response with a status such as 401, 404, or 500 may still resolve to a Response object.
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
Checking the status before parsing the successful response helps the application distinguish server errors from valid weather data.
7. Designing the Weather Application Interface
A weather application should display essential information clearly and make searching for a location simple.
7.1 Recommended UI Components
- SafeAreaView: Helps keep content within the safe screen area.
- Text: Displays headings, temperatures, and descriptions.
- TextInput: Accepts the city name.
- Pressable: Provides interactive search and refresh controls.
- ActivityIndicator: Displays loading feedback.
- View: Groups and arranges interface elements.
- ScrollView: Allows content to scroll on smaller screens.
7.2 Example Interface Layout
----------------------------------
WEATHER APP
----------------------------------
Enter City: [ Mumbai ]
[ Get Weather ]
Mumbai
30°C
Scattered Clouds
Feels Like: 33°C
Humidity: 75%
Wind Speed: 4.1 m/s
[ Refresh Weather ]
----------------------------------
The displayed values are examples only. The running application should show the actual values returned by the weather service.
8. Managing State with useState
The useState hook stores information that can change while the application is running. In a weather application, state is needed for the city input, API response, loading indicator, and error message.
8.1 Defining State Variables
import React, { useState } from "react";
const [city, setCity] = useState("");
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
These declarations must be placed inside a React function component or a custom hook.
| State |
Initial Value |
Purpose |
| city |
Empty string |
Stores the search input. |
| weather |
null |
Stores the successful API response. |
| loading |
false |
Indicates whether a request is in progress. |
| error |
Empty string |
Stores an error message. |
8.2 Updating State
setCity("Mumbai");
setWeather(data);
setLoading(false);
setError("");
Use the setter functions to update state. Avoid mutating the existing weather response object directly.
9. Building the Weather Application
The following example demonstrates city search, API integration, JSON parsing, loading feedback, and error handling. It is intended as a learning implementation for a single weather screen.
Security note: The example uses a placeholder API key. A real API key embedded in a mobile application can potentially be extracted. For production, use a backend service to protect secret credentials when required by the API provider.
9.1 Example App.js
import React, { useState } from "react";
import {
View,
Text,
TextInput,
Pressable,
ActivityIndicator,
ScrollView,
StyleSheet,
SafeAreaView
} from "react-native";
const API_KEY = "YOUR_API_KEY";
const API_URL =
"https://api.openweathermap.org/data/2.5/weather";
export default function App() {
const [city, setCity] = useState("");
const [searchedCity, setSearchedCity] = useState("");
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
async function fetchWeather(cityName = city) {
const trimmedCity = cityName.trim();
if (!trimmedCity) {
setWeather(null);
setError("Please enter a city name.");
return;
}
if (API_KEY === "YOUR_API_KEY") {
setError("Configure a valid weather API key.");
return;
}
setLoading(true);
setError("");
try {
const url =
`${API_URL}?q=${encodeURIComponent(trimmedCity)}` +
`&units=metric&appid=${encodeURIComponent(API_KEY)}`;
const response = await fetch(url);
if (!response.ok) {
if (response.status === 404) {
throw new Error("City not found. Check the spelling.");
}
if (response.status === 401) {
throw new Error("Invalid or inactive API key.");
}
if (response.status === 429) {
throw new Error("API request limit reached.");
}
throw new Error(
`Weather request failed: ${response.status}`
);
}
const data = await response.json();
if (
!data.main ||
!Array.isArray(data.weather) ||
!data.weather[0]
) {
throw new Error("Unexpected weather response.");
}
setWeather(data);
setSearchedCity(data.name || trimmedCity);
} catch (err) {
setWeather(null);
setError(
err instanceof Error
? err.message
: "Unable to retrieve weather information."
);
} finally {
setLoading(false);
}
}
return (
<SafeAreaView style={styles.safeArea}>
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.title}>Weather App</Text>
<Text style={styles.subtitle}>
Check current weather by city
</Text>
<TextInput
style={styles.input}
placeholder="Enter city name"
value={city}
onChangeText={setCity}
onSubmitEditing={() => fetchWeather()}
returnKeyType="search"
autoCapitalize="words"
accessibilityLabel="City name"
/>
<Pressable
style={[
styles.button,
loading && styles.buttonDisabled
]}
onPress={() => fetchWeather()}
disabled={loading}
accessibilityRole="button"
>
<Text style={styles.buttonText}>
{loading ? "Loading..." : "Get Weather"}
</Text>
</Pressable>
{loading && (
<ActivityIndicator
size="large"
style={styles.loader}
accessibilityLabel="Loading weather"
/>
)}
{!!error && (
<Text style={styles.error}>{error}</Text>
)}
{weather && !loading && (
<View style={styles.card}>
<Text style={styles.city}>
{searchedCity}
</Text>
<Text style={styles.temperature}>
{Math.round(weather.main.temp)}°C
</Text>
<Text style={styles.description}>
{weather.weather[0].description}
</Text>
<View style={styles.details}>
<Text style={styles.detailText}>
Feels Like: {Math.round(weather.main.feels_like)}°C
</Text>
<Text style={styles.detailText}>
Humidity: {weather.main.humidity}%
</Text>
{typeof weather.wind?.speed === "number" && (
<Text style={styles.detailText}>
Wind Speed: {weather.wind.speed} m/s
</Text>
)}
{typeof weather.main.pressure === "number" && (
<Text style={styles.detailText}>
Pressure: {weather.main.pressure} hPa
</Text>
)}
</View>
<Pressable
style={styles.refreshButton}
onPress={() => fetchWeather(searchedCity)}
disabled={loading}
accessibilityRole="button"
>
<Text style={styles.refreshText}>
Refresh Weather
</Text>
</Pressable>
</View>
)}
<Text style={styles.footer}>
Weather information is provided by a remote API.
</Text>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: "#F0F7FF"
},
container: {
flexGrow: 1,
justifyContent: "center",
padding: 24
},
title: {
fontSize: 30,
fontWeight: "bold",
textAlign: "center",
color: "#153E75"
},
subtitle: {
fontSize: 15,
textAlign: "center",
color: "#526579",
marginTop: 8,
marginBottom: 24
},
input: {
backgroundColor: "#FFFFFF",
borderWidth: 1,
borderColor: "#CBD5E1",
borderRadius: 10,
padding: 14,
fontSize: 16,
marginBottom: 12
},
button: {
backgroundColor: "#2563EB",
padding: 15,
borderRadius: 10,
alignItems: "center"
},
buttonDisabled: {
opacity: 0.6
},
buttonText: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "bold"
},
loader: {
marginTop: 20
},
error: {
color: "#B91C1C",
backgroundColor: "#FEE2E2",
padding: 12,
borderRadius: 8,
marginTop: 18
},
card: {
backgroundColor: "#FFFFFF",
borderRadius: 16,
padding: 22,
marginTop: 24,
alignItems: "center",
elevation: 3
},
city: {
fontSize: 25,
fontWeight: "bold",
color: "#153E75"
},
temperature: {
fontSize: 52,
fontWeight: "300",
color: "#2563EB",
marginTop: 10
},
description: {
fontSize: 18,
textTransform: "capitalize",
color: "#526579",
marginTop: 4
},
details: {
alignSelf: "stretch",
marginTop: 22,
gap: 12
},
detailText: {
fontSize: 16,
color: "#334155"
},
refreshButton: {
marginTop: 22,
padding: 12,
borderRadius: 8,
backgroundColor: "#DBEAFE",
alignSelf: "stretch",
alignItems: "center"
},
refreshText: {
color: "#1D4ED8",
fontWeight: "bold"
},
footer: {
textAlign: "center",
color: "#64748B",
fontSize: 12,
marginTop: 24
}
});
Code formatting note: The JSX tags and arrow operators in this HTML notes block are escaped for display. When transferring the example into App.js, convert them to normal JSX syntax. For example, replace <SafeAreaView> with the actual SafeAreaView opening tag and use the normal => arrow operator. The JavaScript URL template uses ordinary ampersands in the source code.
9.2 Explanation of the Application
- State initialization: Stores the input city, retrieved weather, loading status, and error message.
- Input validation: Prevents a blank city search.
- URL creation: Uses encodeURIComponent to safely encode the city name.
- Loading feedback: Activates the loading indicator before the request starts.
- API communication: Sends a GET request to the weather endpoint.
- Status checking: Handles common unsuccessful HTTP responses.
- JSON parsing: Converts the successful response into a JavaScript object.
- State update: Stores the returned weather information.
- Error handling: Displays an error when a request fails.
- Cleanup: Resets the loading state inside finally.
9.3 Why Use encodeURIComponent?
City names may contain spaces or special characters. Encoding the value helps create a valid query parameter.
const city = "New Delhi";
const encodedCity = encodeURIComponent(city);
console.log(encodedCity);
Always encode dynamic query values instead of inserting user input directly into a URL.
10. Handling Loading, Success, and Error States
A reliable application must communicate whether it is loading information, has successfully retrieved data, or has encountered a problem.
10.1 Loading State
{loading && (
<ActivityIndicator size="large" />
)}
The loading indicator provides immediate feedback while the application waits for a response.
10.2 Success State
{weather && (
<Text>
Temperature: {Math.round(weather.main.temp)}°C
</Text>
)}
The weather card should render only when valid weather data is available.
10.3 Error State
{error ? (
<Text>{error}</Text>
) : null}
Display a readable error message instead of leaving users with an unexplained blank screen.
10.4 Common HTTP Errors
| Status or Error |
Possible Cause |
Recommended Action |
| 400 Bad Request |
Malformed or missing parameters. |
Verify the endpoint and query parameters. |
| 401 Unauthorized |
Invalid or inactive credentials. |
Check the API key and account configuration. |
| 404 Not Found |
The requested city is not found. |
Check the spelling and location query. |
| 429 Too Many Requests |
The request limit has been exceeded. |
Reduce unnecessary calls and follow provider retry guidance. |
| 5xx Server Error |
The remote service encountered a problem. |
Display a temporary error and retry later. |
| Network error |
Connectivity or connection failure. |
Check internet access and retry. |
| JSON parsing error |
Unexpected or invalid response body. |
Inspect the response format and content. |
11. Using useEffect for Automatic Weather Requests
The useEffect hook runs side effects in a functional component. It can retrieve weather information when a selected city changes.
11.1 Basic useEffect Structure
import React, { useEffect, useState } from "react";
function WeatherExample() {
const [city, setCity] = useState("Mumbai");
const [weather, setWeather] = useState(null);
useEffect(() => {
// Retrieve weather when the selected city changes.
}, [city]);
return null;
}
This example illustrates the hook structure. A complete implementation must include the request logic, error handling, and appropriate handling of stale requests.
11.2 Preventing Stale Responses
If a user searches for two cities quickly, an earlier request may finish after a newer request. Without protection, the earlier response might overwrite the latest result.
useEffect(() => {
let active = true;
async function loadWeather() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error("Weather request failed.");
}
const data = await response.json();
if (active) {
setWeather(data);
setError("");
}
} catch (err) {
if (active) {
setWeather(null);
setError("Unable to load weather.");
}
}
}
loadWeather();
return () => {
active = false;
};
}, [url]);
This is a pattern rather than a complete standalone component. Define url and the state setters in the surrounding component. The active flag prevents stale state updates but does not cancel the network request itself. An AbortController can be used when supported by the runtime and request setup.
12. Displaying Weather Icons and Conditions
Weather icons improve readability by helping users recognize conditions quickly.
12.1 Displaying the Weather Description
const description =
weather?.weather?.[0]?.description ?? "Weather unavailable";
Optional chaining helps prevent errors when a nested property is missing. The nullish coalescing operator supplies a fallback value when the expression is null or undefined.
12.2 Mapping Conditions to Symbols
function getWeatherSymbol(condition) {
const value = condition?.toLowerCase();
if (value === "clear") return "☀️";
if (value === "clouds") return "☁️";
if (value === "rain") return "🌧️";
if (value === "thunderstorm") return "⛈️";
if (value === "snow") return "❄️";
if (value === "mist" || value === "fog") return "🌫️";
return "🌤️";
}
Adjust the mapping to match the weather categories returned by the selected provider.
13. Adding Forecast Information
A weather application can be extended to display predicted conditions for future hours or days. Forecast data may include temperature, precipitation probability, wind conditions, and weather descriptions.
13.1 Current Weather vs. Forecast
| Feature |
Current Weather |
Forecast |
| Purpose |
Displays current observed conditions. |
Displays predicted future conditions. |
| Typical fields |
Temperature, humidity, wind, description. |
Forecast temperature, precipitation, wind, condition. |
| Endpoint |
Current weather endpoint. |
Forecast endpoint supported by the provider. |
| Interface |
Current-weather card. |
Forecast list or horizontal cards. |
13.2 Rendering Forecast Items
import React from "react";
import { FlatList, Text, View } from "react-native";
function ForecastList({ items }) {
return (
<FlatList
data={items}
keyExtractor={(item, index) =>
String(item.dt ?? index)
}
renderItem={({ item }) => (
<View>
<Text>{item.dt_txt ?? "Forecast"}</Text>
<Text>
{item.main?.temp != null
? `${Math.round(item.main.temp)}°C`
: "Temperature unavailable"}
</Text>
<Text>
{item.weather?.[0]?.description ??
"Condition unavailable"}
</Text>
</View>
)}
/>
);
}
export default ForecastList;
This component illustrates rendering forecast data. Connect it to a supported forecast endpoint and adjust the response mapping to the provider's documented schema.
14. Retrieving Weather by Device Location
Another useful feature is automatically retrieving weather for the user's current location. This requires location permissions and a weather endpoint that accepts geographic coordinates.
14.1 Location-Based Workflow
- Explain why location access is useful.
- Request the required device permission.
- Retrieve latitude and longitude using a suitable location library.
- Handle permission denial and unavailable location data.
- Send the coordinates to the weather API.
- Display the returned weather information.
14.2 Example Coordinate-Based URL
const url =
`${API_URL}?lat=${latitude}` +
`&lon=${longitude}` +
`&units=metric&appid=${API_KEY}`;
This example shows the request structure. Define the coordinates from a valid location result and confirm that the endpoint supports these parameters.
For Expo applications, refer to the Expo Location documentation.
14.3 Location Permission Best Practices
- Request permission only when the feature requires it.
- Explain the purpose of location access.
- Provide manual city search as an alternative.
- Handle timeouts and unavailable GPS data.
- Collect only the location information required for the feature.
- Follow applicable privacy and platform requirements.
15. API Key Security
API credentials must be handled carefully. Mobile application packages can be inspected, so a key embedded in the JavaScript bundle should not be considered confidential.
15.1 Security Best Practices
- Never commit real API keys to public repositories.
- Use a protected backend for secret credentials where required.
- Keep development and production credentials separate.
- Apply provider-supported restrictions and usage limits.
- Monitor unexpected requests and usage.
- Avoid logging credentials or sensitive user information.
- Validate inputs before making API calls.
- Use HTTPS for API communication.
- Follow the provider's terms for client-side key usage.
15.2 Environment Variables
Environment variables help manage configuration, but values embedded into a client-side mobile bundle can still be extracted. They do not automatically protect secret API keys.
const WEATHER_API_BASE_URL =
"https://api.openweathermap.org/data/2.5/weather";
For a production architecture, the app can call a backend service. The backend can protect the provider's secret credentials, validate requests, and apply rate limits.
16. Testing the Weather Application
Testing verifies that the application works correctly with valid responses and handles unsuccessful requests without crashing.
16.1 Manual Testing Checklist
- Search for a valid city.
- Search for a city name containing spaces.
- Submit an empty input field.
- Search for an unknown city.
- Verify that the loading indicator appears during requests.
- Check that temperature uses the selected units.
- Verify humidity and wind speed against the returned data.
- Test when the device is offline.
- Test with an invalid API key.
- Test the response to rate limits and server failures.
- Refresh the weather information.
- Test repeated searches for different cities.
- Verify the interface on different screen sizes.
- Check keyboard interaction and accessibility labels.
16.2 Example Test Cases
| Test Case |
Input or Condition |
Expected Result |
| Valid city |
Mumbai |
Weather information appears if the request succeeds. |
| Empty search |
Blank input |
Validation message appears without an API request. |
| Unknown city |
Invalid city name |
A useful error message appears. |
| Invalid API key |
Incorrect credentials |
An authentication error is displayed. |
| Network failure |
Device offline |
The application displays a network error. |
| Repeated search |
Two different cities |
The latest successful result is displayed. |
| Refresh |
Tap the refresh button |
A new request is made for the selected location. |
17. Troubleshooting Common Problems
17.1 Weather Data Is Not Displayed
Possible causes: Incorrect endpoint, invalid API key, unsuccessful HTTP status, or incorrect property access.
- Inspect the HTTP response status.
- Verify the endpoint and query parameters.
- Check the JSON response structure.
- Confirm that state is updated after successful parsing.
- Check the conditions used to render the weather card.
17.2 Temperature Is Undefined
Ensure that the code accesses the correct nested property.
// Incorrect for the example response:
const temperature = data.temp;
// Correct for the example current-weather response:
const temperature = data.main.temp;
17.3 City Names with Spaces Fail
Encode the city name before adding it to the query string.
const city = "New Delhi";
const url =
`${API_URL}?q=${encodeURIComponent(city)}` +
`&units=metric&appid=${API_KEY}`;
17.4 Loading Indicator Does Not Disappear
Make sure loading is reset whether the request succeeds or fails.
try {
// Perform the API request.
} catch (error) {
// Handle the error.
} finally {
setLoading(false);
}
17.5 API Key Error
Check the API key, account configuration, endpoint permissions, and provider activation requirements.
17.6 Network Request Fails
- Verify that the device has internet access.
- Confirm that the endpoint uses HTTPS.
- Inspect the response status and error message.
- Check whether the service is available.
- Confirm that the API usage limit has not been exceeded.
18. Performance Optimization
Performance optimization helps the application remain responsive and avoids unnecessary API traffic.
18.1 Avoid Unnecessary Requests
Trigger requests when the user submits a city, selects a location, or refreshes the result. Avoid sending a request for every keystroke in the search field.
18.2 Debounce Search Suggestions
For automatic search suggestions, debounce input so that the application waits briefly after typing stops before making a request. This can reduce unnecessary API calls.
18.3 Cache Weather Results
Caching can improve responsiveness and support limited offline access. Store the retrieval time and clearly label cached results so that users do not mistake old information for current conditions.
18.4 Prevent Stale Data
Weather conditions change frequently. Show a last-updated timestamp where appropriate and refresh data according to the application's requirements and the provider's usage limits.
18.5 Separate API Logic from UI Components
Moving API logic into a service module makes the code easier to test, reuse, and maintain.
// services/weatherService.js
const BASE_URL =
"https://api.openweathermap.org/data/2.5/weather";
export async function getCurrentWeather(city, apiKey) {
const url =
`${BASE_URL}?q=${encodeURIComponent(city)}` +
`&units=metric&appid=${encodeURIComponent(apiKey)}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Weather request failed: ${response.status}`
);
}
return response.json();
}
This example accepts an API key as a parameter for demonstration. For production use, protect secret credentials on a backend when required.
19. Recommended Project Structure
A logical folder structure helps separate user interface components, API services, and helper functions.
WeatherApp/
├── App.js
├── components/
│ ├── WeatherCard.js
│ ├── SearchBar.js
│ ├── LoadingView.js
│ └── ErrorMessage.js
├── screens/
│ └── WeatherScreen.js
├── services/
│ └── weatherService.js
├── utils/
│ └── weatherHelpers.js
└── assets/
└── icons/
The exact structure depends on the project template. An Expo Router project may use route files inside an app directory instead of a single App.js screen.
20. Mini Project: Weather Application
Build a complete weather application that retrieves current weather information for a city entered by the user.
20.1 Project Requirements
- Create a React Native user interface.
- Allow users to enter a city name.
- Connect to a weather REST API.
- Display temperature, weather description, humidity, and wind speed.
- Show loading feedback during requests.
- Display helpful errors for invalid input and unsuccessful requests.
- Add a refresh feature.
- Organize the application into reusable components.
- Keep API request logic separate where appropriate.
- Test the application on an emulator or physical device.
20.2 Advanced Features
- Location-based weather.
- Hourly and multi-day forecasts.
- Favorite cities.
- Celsius and Fahrenheit selection.
- Weather icons and condition-based themes.
- Search suggestions and recent locations.
- Offline display of labelled cached data.
- Pull-to-refresh interaction.
- Automated tests for API requests and interface states.
20.3 Project Evaluation Criteria
| Area |
Evaluation Criteria |
| API integration |
Correct endpoint, request parameters, and response processing. |
| State management |
Appropriate loading, success, and error states. |
| UI design |
Clear layout and readable weather information. |
| Reliability |
Handles invalid input, connectivity problems, and server errors. |
| Security |
Protects credentials and avoids exposing sensitive information. |
| Code quality |
Uses reusable components and maintainable code. |
21. Interview Questions and Answers
Q1. What is a REST API?
Answer: A REST API is an interface that exposes resources over HTTP and commonly uses methods such as GET, POST, PUT, PATCH, and DELETE.
Q2. Why does a weather application need an API?
Answer: It retrieves weather observations and forecast information from a remote service instead of relying on hardcoded data.
Q3. What is the Fetch API?
Answer: Fetch is a Promise-based JavaScript API used to make HTTP requests and process server responses.
Q4. Why are async and await used?
Answer: They make asynchronous operations easier to write and understand by allowing code to follow a sequential structure.
Q5. What is JSON?
Answer: JSON is a text-based format for exchanging structured data between systems.
Q6. What does response.json() do?
Answer: It reads the response body and parses the JSON text into a JavaScript value.
Q7. Why should response.ok be checked?
Answer: Fetch may resolve even when the server returns an HTTP error status. Checking response.ok allows the application to identify unsuccessful responses.
Q8. How is useState useful in a weather application?
Answer: It stores values such as the search input, weather response, loading status, and error message.
Q9. What is useEffect used for?
Answer: It runs side effects in response to component lifecycle events or changes in dependencies, such as retrieving weather data when a selected city changes.
Q10. Why is a loading indicator important?
Answer: It communicates that a request is in progress and gives users feedback during network delays.
Q11. How should API errors be handled?
Answer: Check response status codes, catch request and parsing errors, display useful messages, and reset loading state in finally.
Q12. Why use encodeURIComponent?
Answer: It encodes a value so it can be safely included in a URL component, such as a city name in a query parameter.
Q13. How can API keys be protected?
Answer: Keep secret credentials on a protected backend when necessary, apply provider-supported restrictions, and monitor usage.
Q14. How can unnecessary API calls be reduced?
Answer: Trigger requests on submission, debounce live search, cache results appropriately, and avoid duplicate requests.
Q15. What is the difference between current weather and a forecast?
Answer: Current weather describes present observations, while forecast data provides predictions for future periods.
22. Practice Exercises
- Create a React Native screen with a city input and search button.
- Connect the application to a weather REST API.
- Display the temperature in Celsius.
- Add humidity and wind speed to the weather card.
- Show a loading indicator during network requests.
- Display a validation message for empty input.
- Handle invalid API keys and city-not-found errors.
- Move the API request into a separate service module.
- Add a refresh button and last-updated timestamp.
- Extend the application to display a forecast using FlatList.
23. Quick Revision Checklist
- REST APIs allow applications to communicate with remote services.
- GET requests are commonly used to retrieve weather information.
- API endpoints and parameters must match provider documentation.
- Fetch sends HTTP requests from React Native.
- response.ok helps identify unsuccessful HTTP responses.
- response.json() parses a JSON response body.
- async and await simplify asynchronous code.
- useState manages the city, weather, loading, and error values.
- useEffect can trigger requests when dependencies change.
- Loading, success, and error states improve usability.
- Dynamic query parameters should be encoded correctly.
- API credentials must be managed according to security requirements.
- Testing should cover invalid input, network failures, and server errors.
- Reusable components and service modules improve maintainability.
- Cached weather information should be labelled and timestamped appropriately.
24. Conclusion
Developing a weather application using a REST API is a practical way to learn React Native networking, asynchronous JavaScript, JSON parsing, state management, and interface development. By integrating a weather service, developers can retrieve real weather information and present it through an interactive mobile application.
A reliable weather application should validate user input, handle unsuccessful responses, display loading feedback, protect API credentials, and show the data returned by the server. Additional features such as location-based weather, forecasts, saved cities, and offline caching can make the application more useful.
To continue learning, visit the React Native Training course at JustAcademy, register for the course demo, or explore the JustAcademy website.