CodeBlanks Logo Icon CodeBlanks

Putting it together

Combine all layers into a working app.

Putting it together

In the last lesson we integrate all parts. So far: skeleton (App + tasks state), Context (TasksContext + useTasks), API (useEffect + fetch), navigation (Tab.Navigator). Now we add one last piece: a loading state.

The loading state shows the user an indicator while the API request is in flight. It starts with useState(true); when fetch finishes setLoading(false) is called. TasksScreen shows <ActivityIndicator /> if loading. This makes the app feel gentler. In the last lesson all parts (Context + hooks + API + navigation + loading) come together and a complete app emerges.

Practice Add a loading state

Add a loading state to the existing App component. Initialize it with const [loading, setLoading] = useState(true). When the fetch inside useEffect finishes call setLoading(false). Add loading to the value of TasksContext.Provider.

Starter code

App.js
import React, { useState, useEffect, createContext, useContext } from 'react';
import { Text, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const TasksContext = createContext();

export function useTasks() {
  return useContext(TasksContext);
}

const Tab = createBottomTabNavigator();

function TasksScreen() {
  const { tasks, loading } = useTasks();
  if (loading) return <ActivityIndicator />;
  return <Text>Tasks: {tasks.length}</Text>;
}

function StatsScreen() {
  const { tasks } = useTasks();
  return <Text>Stats</Text>;
}

function App() {
  const [tasks, setTasks] = useState([]);
  // Add loading state

  useEffect(() => {
    fetch('https://api.example.com/tasks')
      .then((res) => res.json())
      .then((data) => setTasks(data));
  }, []);
  return (
    <TasksContext.Provider value={{ tasks, setTasks }}>
      <NavigationContainer>
        <Tab.Navigator>
          <Tab.Screen name="Tasks" component={TasksScreen} />
          <Tab.Screen name="Stats" component={StatsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    </TasksContext.Provider>
  );
}

Sample solution

App.js
import React, { useState, useEffect, createContext, useContext } from "react";
import { Text, ActivityIndicator } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

const TasksContext = createContext();

export function useTasks() {
  return useContext(TasksContext);
}

const Tab = createBottomTabNavigator();

function TasksScreen() {
  const { tasks, loading } = useTasks();
  if (loading) return <ActivityIndicator />;
  return <Text>Tasks: {tasks.length}</Text>;
}

function StatsScreen() {
  const { tasks } = useTasks();
  return <Text>Stats</Text>;
}

function App() {
  const [tasks, setTasks] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("https://api.example.com/tasks")
      .then((res) => res.json())
      .then((data) => {
        setTasks(data);
        setLoading(false);
      });
  }, []);

  return (
    <TasksContext.Provider value={{ tasks, setTasks, loading }}>
      <NavigationContainer>
        <Tab.Navigator>
          <Tab.Screen name="Tasks" component={TasksScreen} />
          <Tab.Screen name="Stats" component={StatsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    </TasksContext.Provider>
  );
}

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What do Context + hooks + API + navigation form together?

App.js
App = Context + hooks + API + navigation
  • A book
  • A screen
  • A test
  • A full app Correct answer

Explanation: These four form a full app.

2 Match each piece to its role

Term Meaning
Context Shares state
hooks Wraps logic
API Loads data
navigation Links screens
loading Shows waiting

3 Add loading to the value

Question
value={{ tasks, ____ }}
Answer
value={{ tasks, loading }}

Explanation: loading is added to the context value.

4 What is added in the integration step?

App.js
useState(true) + setLoading(false)
  • Loading state Correct answer
  • A new font
  • A logo
  • A color palette

Explanation: A loading state is added in the integration step.

All lessons in Intermediate