CodeBlanks Logo Icon CodeBlanks

Offline

Add offline support and caching.

What is an offline cache?

An offline cache lets the app work in low connectivity. With @react-native-async-storage/async-storage we save tasks on the device; AsyncStorage is a key-value store. When the internet is up we pull fresh data from the API; when it is down we read from the cache.

The NetInfo library watches the connection: online or offline. The useNetInfo() hook gives this as state. First the cache loads, then if the network is up the API refreshes. This pattern is known as stale-while-revalidate; the user sees content instantly and refresh happens in the background.

Practice Add the cache loading flow

On top of the previous code add a loadCache function. It should call AsyncStorage.getItem('tasks'); if a value comes back, parse it with JSON.parse and write it with setTasks.

Starter code

App.js
import React, { useState, createContext, useContext } from 'react';
import { Text, View } from 'react-native';

const AuthContext = createContext(null);
export function useAuth() { return useContext(AuthContext); }

function App() {
  const [tasks, setTasks] = useState([]);
  const [user, setUser] = useState(null);
  return (
    <AuthContext.Provider value={{ user, setUser }}>
      <View>
        <Text>Field Report</Text>
      </View>
    </AuthContext.Provider>
  );
}

export function useCamera() {
  const [photo, setPhoto] = useState(null);
  const takePhoto = async () => {
    setPhoto('photo-uri');
  };
  return { photo, takePhoto };
}

// Add the loadCache function here

Sample solution

App.js
import React, { useState, createContext, useContext } from 'react';
import { Text, View } from 'react-native';

const AuthContext = createContext(null);
export function useAuth() { return useContext(AuthContext); }

function App() {
  const [tasks, setTasks] = useState([]);
  const [user, setUser] = useState(null);
  return (
    <AuthContext.Provider value={{ user, setUser }}>
      <View>
        <Text>Field Report</Text>
      </View>
    </AuthContext.Provider>
  );
}

export function useCamera() {
  const [photo, setPhoto] = useState(null);
  const takePhoto = async () => {
    setPhoto('photo-uri');
  };
  return { photo, takePhoto };
}

async function loadCache() {
  const raw = await AsyncStorage.getItem('tasks');
  if (raw) {
    setTasks(JSON.parse(raw));
  }
}

Watching connection with NetInfo

The useNetInfo() hook gives the connection state. The isConnected field is true when online, false when offline. Based on this you decide whether to call the API.

Example: const net = useNetInfo(); if (net.isConnected) { fetchTasks(); }. When the connection drops you keep reading from the cache; the user does not notice. When the connection returns you pull fresh data and refresh the cache. This flow is the core of field apps; the internet may not always be there.

Questions and answers

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

1 What happens when NetInfo isConnected is false?

App.js
const net = useNetInfo();
  • The app closes
  • Read from cache Correct answer
  • New tasks are added
  • A photo is taken

Explanation: When offline, read from the cache.

2 AsyncStorage getItem call

Question
const raw = await AsyncStorage.____('tasks');
Answer
const raw = await AsyncStorage.getItem('tasks');

Explanation: getItem reads the value for a key.

3 Match each flow piece to its role

Term Meaning
AsyncStorage Stores on device
NetInfo Watches connection
getItem Reads a value
setItem Writes a value

All lessons in Advanced