skill
Expo Data Fetching
Framework (OSS). Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, loading/empty/error screen states, and Expo Router data loaders (`useLoaderData`).
About
# Expo Networking
**You MUST use this skill for ANY networking work including API requests, data fetching, caching, or network debugging.**
## References
Consult these resources as needed:
``` references/ expo-router-loaders.md Route-level data loading with Expo Router loaders (web, SDK 55+) offline-and-cancellation.md NetInfo network status, offline-first React Query, AbortController ```
## When to Use
Use this skill when:
- Implementing API requests - Setting up data fetching (React Query, SWR) - Using Expo Router data loaders (`useLoaderData`, web SDK 55+) - Debugging network failures - Implementing caching strategies - Handling offline scenarios - Authentication/token management - Configuring API URLs and environment variables
## Preferences
- Avoid axios, prefer expo/fetch
## Every Screen Has Four States
Design **loading**, **error**, **empty**, and **content** for screens that load data. These can overlap: a refresh error should coexist with cached content.
- **Loading ≠ empty.** Empty means *resolved with zero items*, not missing data. Handle initial loading, failure, and hydration before checking list length. In TanStack Query v5, `isLoading` means the first fetch is running; a disabled or offline-paused query can have no data without being loading. Show the prerequisite or offline state in that case. - **Empty is a designed state, not a blank list.** Use `ListEmptyComponent` on FlatList/FlashList: explain why it is empty and offer the relevant next action. "No items yet" can offer Create; "No results" should offer changing or clearing the search/filter. - **Refetches keep stale content.** Render cached `data` even if a refresh fails, with a nonblocking error and retry. Use `isLoading` for first-fetch spinners and `isFetching` for background activity; prefer a skeleton for a slow initial load with a known layout, and `RefreshControl` for user-initiated refresh. - **Gate on hydration.** When initial UI or a redirect depends on persisted state (auth token, onboarding flag), the root layout renders nothing - or the splash - until that state has loaded. Deciding on unhydrated state flashes the wrong screen on every cold start and misroutes deep links that arrive before hydration.
**Saves preserve work.** While a mutation is pending, disable repeat submission. On failure, retain the draft, show an inline error, and let the user retry; clear or dismiss only after success. If updating optimistically, restore the previous value or mark the edit as unsynced on failure. Verify with a failed save followed by retry.
## Common Issues & Solutions
### 1. Basic Fetch Usage
**Simple GET request**:
```tsx const fetchUser = async (userId: string) => { const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
return response.json(); }; ```
**POST request with body**:
```tsx const createUser = async (userData: UserData) => { const response = await fetch("https://api.example.com/users", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify(userData), });
if (!response.ok) { const error = await response.json(); throw new Error(error.message); }
return response.json(); }; ```
---
### 2. React Query (TanStack Query)
**Setup**:
```tsx // app/_layout.tsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, // 5 minutes retry: 2, }, }, });
export default function RootLayout() { return ( <QueryClientProvider client={queryClient}> <Stack /> </QueryClientProvider> ); } ```
**Fetching data**:
```tsx import { useQuery } from "@tanstack/react-query";
function UserProfile({ userId }: { userId: string }) { const { data, fetchStatus, error, refetch } = useQuery({ queryKey: ["user", userId], queryFn: () => fetchUser(userId), });
if (data === undefined) { if (error) return <ErrorState message={error.message} onRetry={() => refetch()} />; if (fetchStatus === "paused") return <OfflineState />; return <Loading />; }
return ( <> {error && <InlineError message="Could not refresh. Showing saved data." onRetry={() => refetch()} />} {data === null ? <EmptyState message="User not found" /> : <Profile user={data} />} </> ); } ```
**Mutations**:
```tsx import { useMutation, useQueryClient } from "@tanstack/react-query";
function CreateUserForm() { const queryClient = useQueryClient();
const mutation = useMutation({ mutationFn: createUser, onSuccess: () => { // Invalidate and refetch queryClient.invalidateQueries({ queryKey: ["users"] }); }, });
const handleSubmit = (data: UserData) => { if (mutation.isPending) return; mutation.mutate(
Install
Run this command
git clone https://github.com/expo/skills && cp -r skills/plugins/expo/skills/expo-data-fetching ~/.claude/skills/Works with
Manual steps
Clone the repository and copy the `plugins/expo/skills/expo-data-fetching` folder into your Claude skills directory. Compatible with Claude Code, Cursor, Codex, and any Agent Skills-compatible agent.
Frequently asked questions
What is the Expo Data Fetching skill?
Framework (OSS). Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, loading/empty/error screen states, and Expo Router data loaders (`useLoaderData`).
How do I install Expo Data Fetching?
Run this in your terminal:
git clone https://github.com/expo/skills && cp -r skills/plugins/expo/skills/expo-data-fetching ~/.claude/skills/Which AI tools does Expo Data Fetching work with?
It works with claude_app, claude_code, claude_api, cursor, codex, windsurf, cline, zed.
Who made Expo Data Fetching?
Expo, released under the MIT license.
Is Expo Data Fetching free?
Yes, it is free to use under the MIT license.
npx skills add google/agents-cli
npx skills add google/agents-cli
npx skills add google/agents-cli
npx skills add google/agents-cli
npx skills add google/agents-cli
npx skills add prisma/skills
Audit before you install
Run any source through our checks - AI visibility, security, performance, and stack detection.
Automated Web Security Scan
security
PageSpeed Analyzer
performance
AI Content Quality Test
arabic content
AI Agent / MCP Server Tester
ai testing
Site Stack Detector
migration
AI SEO / AEO / GEO Audit
ai visibility
llms.txt Generator
ai visibility
Readability Score
arabic content
Schema / JSON-LD Builder
ai visibility
AI Cost Calculator
ai testing
Headline Analyzer
arabic content