Build a Stunning Weather App with React Native: A Step-by-Step Beginner’s Guide

2.92K 0 0 0 0

📘 Chapter 4: Managing State and Handling User Input

🧭 What You’ll Learn

By the end of this chapter, you’ll be able to:

  • Understand how React Native uses state for dynamic UIs
  • Work with useState and useEffect to manage state changes
  • Handle user input with TextInput
  • Add conditional rendering based on state
  • Cleanly separate UI and state logic
  • Reset and validate user input
  • Create responsive, interactive weather queries

🌟 Why State Matters in React Native

State is how your app remembers data—like what the user typed, whether it's loading, or what the current weather is. Without state, your app would be static and unresponsive.

🔁 State Examples in This Project

  • City input (city)
  • Weather data object (weather)
  • Loading state (isLoading)
  • Error messages (error)
  • Last searched value (lastSearch)

🔧 Step-by-Step: Using useState for Weather Data

Import React Hooks

jsx

 

import React, { useState, useEffect } from 'react';


Define Your State Variables

jsx

 

const [city, setCity] = useState('');

const [weather, setWeather] = useState(null);

const [loading, setLoading] = useState(false);

const [error, setError] = useState('');


🔤 Handling User Input with TextInput

TextInput is the primary way users interact with forms in React Native.

🔹 Controlled Input Pattern

jsx

 

<TextInput

  style={styles.input}

  placeholder="Enter city name"

  value={city}

  onChangeText={setCity}

/>

This keeps the city value synced with the input box.


️ Triggering State Updates with Button

jsx

 

<TouchableOpacity onPress={fetchWeather} style={styles.button}>

  <Text style={styles.buttonText}>Get Weather</Text>

</TouchableOpacity>

When the user presses the button, the fetchWeather function runs and updates state.


🧠 Full Example: Interactive State-Driven UI

jsx

 

const fetchWeather = async () => {

  if (!city.trim()) {

    setError('Please enter a city');

    return;

  }

 

  setLoading(true);

  setError('');

  setWeather(null);

 

  try {

    const response = await getWeatherByCity(city);

    setWeather(response);

  } catch (err) {

    setError('City not found.');

  } finally {

    setLoading(false);

  }

};


🔍 Input Validation Logic

Scenario

Response

Empty input

Show "Please enter a city"

API returns 404

Show "City not found"

Successful fetch

Show temperature and details


🔄 Reacting to State Changes with useEffect

Want to fetch data when the user changes city automatically?

jsx

 

useEffect(() => {

  if (city.length >= 3) {

    const timeout = setTimeout(fetchWeather, 1000);

    return () => clearTimeout(timeout);

  }

}, [city]);

This debounced effect runs fetchWeather 1 second after typing stops.


🧱 Sample Full Component: Weather Input

jsx

 

export default function WeatherInput({ onFetch }) {

  const [city, setCity] = useState('');

  const [error, setError] = useState('');

 

  const handleSubmit = () => {

    if (!city.trim()) {

      setError('Enter a city name');

      return;

    }

    onFetch(city);

    setError('');

    setCity('');

  };

 

  return (

    <View>

      <TextInput

        style={styles.input}

        placeholder="City"

        value={city}

        onChangeText={setCity}

      />

      <TouchableOpacity onPress={handleSubmit} style={styles.button}>

        <Text style={styles.buttonText}>Search</Text>

      </TouchableOpacity>

      {error ? <Text style={styles.error}>{error}</Text> : null}

    </View>

  );

}


🔁 Conditional Rendering in React Native

Use conditions to display UI based on state.

jsx

 

{loading && <ActivityIndicator size="large" color="#0000ff" />}

{error ? <Text style={styles.error}>{error}</Text> : null}

{weather && (

  <View>

    <Text>{weather.temp}°C</Text>

    <Text>{weather.description}</Text>

  </View>

)}


🧩 Resetting Input After Submission

Reset input with setCity('') inside the form submit handler.


🧱 Table: Common State Hooks and Usage

Hook

Purpose

useState

Store and update dynamic values

useEffect

Run side effects like API calls or timers

useRef

Store references to input fields or timers

useMemo

Optimize expensive calculations


🎯 Best Practices

  • Validate input before calling the API
  • Clear previous weather result before loading
  • Use trim() to ignore whitespace inputs
  • Display fallback text or loading spinners
  • Avoid long chains of nested ternaries in JSX

🧠 Bonus: Preserving State Across Sessions

To store last searched city:

bash

 

npm install @react-native-async-storage/async-storage

Then:

jsx

 

import AsyncStorage from '@react-native-async-storage/async-storage';

 

const saveCity = async (city) => {

  await AsyncStorage.setItem('lastCity', city);

};

 

const loadCity = async () => {

  const saved = await AsyncStorage.getItem('lastCity');

  if (saved) setCity(saved);

};

Call loadCity() in useEffect() on app load.


Summary

You now know how to:

  • Capture user input with TextInput
  • Use useState and useEffect for dynamic data handling
  • Display real-time weather updates from user actions
  • Validate inputs and show meaningful error messages
  • Enhance user experience with loading and reset logic

Back

FAQs


❓1. Do I need to know React to build a React Native weather app?

Answer:
While React Native shares many concepts with React (like components, props, and state), you don’t need to be an expert in React to start. Basic knowledge of JavaScript and understanding of components will help you get going quickly.

❓2. What’s the difference between Expo and React Native CLI?

Answer:
Expo is a framework and platform that simplifies React Native development. It’s great for beginners.
React Native CLI provides full native access and is preferred for advanced, production-grade apps. For this weather app, Expo is usually enough.

❓3. Which weather API should I use?

Answer:
You can use any public weather API, but OpenWeatherMap is beginner-friendly, well-documented, and offers a free tier with real-time weather data, making it ideal for this project.

❓4. Is this weather app cross-platform?

Answer:
Yes! React Native apps work on both Android and iOS. You’ll be building one codebase that runs on both platforms with native-like performance.

❓5. Can I use geolocation to show weather for the current location?

Answer:
Absolutely. React Native supports location access through packages like expo-location or react-native-geolocation-service, which lets you fetch the user’s coordinates and use them in your API requests.

❓6. Do I need to pay for an API key?

Answer:
No. Most APIs like OpenWeatherMap offer a free tier that includes current weather data, which is enough for this app. Just sign up and grab your API key from their dashboard.

❓7. How do I manage the app’s state?

Answer:
This app uses React Hooks—mainly useState for managing input and weather data, and useEffect for API calls. For more advanced apps, you might consider using context or libraries like Redux.

❓8. How do I style the UI in React Native?

Answer:
React Native uses the StyleSheet.create() method to define CSS-like styles. You can also use Flexbox for layout and third-party libraries like react-native-elements or styled-components for more flexibility.

❓9. Can I deploy this app to the Google Play Store or Apple App Store?

Answer:
Yes, with additional steps. You’ll need to create a developer account for each store, build release versions, test thoroughly, and follow each platform’s publishing guidelines. Expo also offers services like EAS Build to simplify deployment.

❓10. What else can I add to make the app more advanced?

Answer:
You can add features like:

  • 7-day weather forecasts
  • Hourly breakdowns
  • Save favorite cities
  • Background images based on weather
  • Dark mode support
  • Weather animations (e.g., rain, sun, snow)


These upgrades help turn a simple app into a portfolio-level project.