Skip to main content Inicio Creadores arareusername tbats-dev native-data-fetching
native-data-fetching Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).
Ir a la instalación Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/ARareUsername/tbats-dev --skill native-data-fetchingEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... UI/UX design intelligence for web and mobile. Searchable local database with 50+ styles, 161 color palettes, 57 font pairings, 161 product types, 99 UX guidelines, and 25 chart types across 10 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui, and HTML/CSS). Use when designing, building, or reviewing UI: pages, components, color schemes, typography, layout, accessibility, animation, or data visualization.
Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
Explorador de archivos
3 archivos name native-data-fetching description Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`). risk unknown source https://github.com/expo/skills/tree/main/plugins/expo/skills/native-data-fetching source_repo expo/skills source_type official date_added "2026-07-01T00:00:00.000Z" license MIT license_source https://github.com/expo/skills/blob/main/LICENSE
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+)
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
Common Issues & Solutions
1. Basic Fetch Usage
Simple GET request :
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 :
const createUser = async (userData : UserData ) => {
const response = await fetch ( , {
: ,
: {
: ,
: ,
},
: . (userData),
});
(!response. ) {
error = response. ();
(error. );
}
response. ();
};
"https://api.example.com/users"
method
"POST"
headers
"Content-Type"
"application/json"
Authorization
`Bearer ${token} `
body
JSON
stringify
if
ok
const
await
json
throw
new
Error
message
return
json
2. React Query (TanStack Query)
import { QueryClient , QueryClientProvider } from "@tanstack/react-query" ;
const queryClient = new QueryClient ({
defaultOptions : {
queries : {
staleTime : 1000 * 60 * 5 ,
retry : 2 ,
},
},
});
export default function RootLayout ( ) {
return (
<QueryClientProvider client ={queryClient} >
<Stack />
</QueryClientProvider >
);
}
import { useQuery } from "@tanstack/react-query" ;
function UserProfile ({ userId }: { userId: string } ) {
const { data, isLoading, error, refetch } = useQuery ({
queryKey : ["user" , userId],
queryFn : () => fetchUser (userId),
});
if (isLoading) return <Loading /> ;
if (error) return <Error message ={error.message} /> ;
return <Profile user ={data} /> ;
}
import { useMutation, useQueryClient } from "@tanstack/react-query" ;
function CreateUserForm ( ) {
const queryClient = useQueryClient ();
const mutation = useMutation ({
mutationFn : createUser,
onSuccess : () => {
queryClient.invalidateQueries ({ queryKey : ["users" ] });
},
});
const handleSubmit = (data : UserData ) => {
mutation.mutate (data);
};
return <Form onSubmit ={handleSubmit} isLoading ={mutation.isPending} /> ;
}
3. Error Handling Comprehensive error handling :
class ApiError extends Error {
constructor (message : string , public status : number , public code ?: string ) {
super (message);
this .name = "ApiError" ;
}
}
const fetchWithErrorHandling = async (url : string , options ?: RequestInit ) => {
try {
const response = await fetch (url, options);
if (!response.ok ) {
const error = await response.json ().catch (() => ({}));
throw new ApiError (
error.message || "Request failed" ,
response.status ,
error.code
);
}
return response.json ();
} catch (error) {
if (error instanceof ApiError ) {
throw error;
}
throw new ApiError ("Network error" , 0 , "NETWORK_ERROR" );
}
};
const fetchWithRetry = async (
url : string ,
options ?: RequestInit ,
retries = 3
) => {
for (let i = 0 ; i < retries; i++) {
try {
return await fetchWithErrorHandling (url, options);
} catch (error) {
if (i === retries - 1 ) throw error;
await new Promise ((r ) => setTimeout (r, Math .pow (2 , i) * 1000 ));
}
}
};
4. Authentication import * as SecureStore from "expo-secure-store" ;
const TOKEN_KEY = "auth_token" ;
export const auth = {
getToken : () => SecureStore .getItemAsync (TOKEN_KEY ),
setToken : (token : string ) => SecureStore .setItemAsync (TOKEN_KEY , token),
removeToken : () => SecureStore .deleteItemAsync (TOKEN_KEY ),
};
const authFetch = async (url : string , options : RequestInit = {} ) => {
const token = await auth.getToken ();
return fetch (url, {
...options,
headers : {
...options.headers ,
Authorization : token ? `Bearer ${token} ` : "" ,
},
});
};
let isRefreshing = false ;
let refreshPromise : Promise <string > | null = null ;
const getValidToken = async (): Promise <string > => {
const token = await auth.getToken ();
if (!token || isTokenExpired (token)) {
if (!isRefreshing) {
isRefreshing = true ;
refreshPromise = refreshToken ().finally (() => {
isRefreshing = false ;
refreshPromise = null ;
});
}
return refreshPromise!;
}
return token;
};
5. Offline Support import NetInfo from "@react-native-community/netinfo" ;
function useNetworkStatus ( ) {
const [isOnline, setIsOnline] = useState (true );
useEffect (() => {
return NetInfo .addEventListener ((state ) => {
setIsOnline (state.isConnected ?? true );
});
}, []);
return isOnline;
}
Offline-first with React Query :
import { onlineManager } from "@tanstack/react-query" ;
import NetInfo from "@react-native-community/netinfo" ;
onlineManager.setEventListener ((setOnline ) => {
return NetInfo .addEventListener ((state ) => {
setOnline (state.isConnected ?? true );
});
});
6. Environment Variables Using environment variables for API configuration :
Expo supports environment variables with the EXPO_PUBLIC_ prefix. These are inlined at build time and available in your JavaScript code.
EXPO_PUBLIC_API_URL =https :
EXPO_PUBLIC_API_VERSION =v1
const API_URL = process.env .EXPO_PUBLIC_API_URL ;
const fetchUsers = async ( ) => {
const response = await fetch (`${API_URL} /users` );
return response.json ();
};
Environment-specific configuration :
EXPO_PUBLIC_API_URL =http :
EXPO_PUBLIC_API_URL =https :
Creating an API client with environment config :
const BASE_URL = process.env .EXPO_PUBLIC_API_URL ;
if (!BASE_URL ) {
throw new Error ("EXPO_PUBLIC_API_URL is not defined" );
}
export const apiClient = {
get : async <T,>(path : string ): Promise <T> => {
const response = await fetch (`${BASE_URL} ${path} ` );
if (!response.ok ) throw new Error (`HTTP ${response.status} ` );
return response.json ();
},
post : async <T,>(path : string , body : unknown ): Promise <T> => {
const response = await fetch (`${BASE_URL} ${path} ` , {
method : "POST" ,
headers : { "Content-Type" : "application/json" },
body : JSON .stringify (body),
});
if (!response.ok ) throw new Error (`HTTP ${response.status} ` );
return response.json ();
},
};
Only variables prefixed with EXPO_PUBLIC_ are exposed to the client bundle
Never put secrets (API keys with write access, database passwords) in EXPO_PUBLIC_ variables—they're visible in the built app
Environment variables are inlined at build time , not runtime
Restart the dev server after changing .env files
For server-side secrets in API routes, use variables without the EXPO_PUBLIC_ prefix
declare global {
namespace NodeJS {
interface ProcessEnv {
EXPO_PUBLIC_API_URL : string ;
EXPO_PUBLIC_API_VERSION ?: string ;
}
}
}
export {};
7. Request Cancellation useEffect (() => {
const controller = new AbortController ();
fetch (url, { signal : controller.signal })
.then ((response ) => response.json ())
.then (setData)
.catch ((error ) => {
if (error.name !== "AbortError" ) {
setError (error);
}
});
return () => controller.abort ();
}, [url]);
With React Query (automatic):
Decision Tree User asks about networking
|-- Route-level data loading (web, SDK 55+)?
| \-- Expo Router loaders — see references/expo-router-loaders.md
|
|-- Basic fetch?
| \-- Use fetch API with error handling
|
|-- Need caching/state management?
| |-- Complex app -> React Query (TanStack Query)
| \-- Simpler needs -> SWR or custom hooks
|
|-- Authentication?
| |-- Token storage -> expo-secure-store
| \-- Token refresh -> Implement refresh flow
|
|-- Error handling?
| |-- Network errors -> Check connectivity first
| |-- HTTP errors -> Parse response, throw typed errors
| \-- Retries -> Exponential backoff
|
|-- Offline support?
| |-- Check status -> NetInfo
| \-- Queue requests -> React Query persistence
|
|-- Environment/API config?
| |-- Client-side URLs -> EXPO_PUBLIC_ prefix in .env
| |-- Server secrets -> Non-prefixed env vars (API routes only)
| \-- Multiple environments -> .env.development, .env.production
|
\-- Performance?
|-- Caching -> React Query with staleTime
|-- Deduplication -> React Query handles this
\-- Cancellation -> AbortController or React Query
Common Mistakes const data = await fetch (url).then ((r ) => r.json ());
Right: Check response status
const response = await fetch (url);
if (!response.ok ) throw new Error (`HTTP ${response.status} ` );
const data = await response.json ();
Wrong: Storing tokens in AsyncStorage
await AsyncStorage .setItem ("token" , token);
Right: Use SecureStore for sensitive data
await SecureStore .setItemAsync ("token" , token);
Example Invocations User: "How do I make API calls in React Native?"
-> Use fetch, wrap with error handling
User: "Should I use React Query or SWR?"
-> React Query for complex apps, SWR for simpler needs
User: "My app needs to work offline"
-> Use NetInfo for status, React Query persistence for caching
User: "How do I handle authentication tokens?"
-> Store in expo-secure-store, implement refresh flow
User: "API calls are slow"
-> Check caching strategy, use React Query staleTime
User: "How do I configure different API URLs for dev and prod?"
-> Use EXPOPUBLIC env vars with .env.development and .env.production files
User: "Where should I put my API key?"
-> Client-safe keys: EXPOPUBLIC in .env. Secret keys: non-prefixed env vars in API routes only
User: "How do I load data for a page in Expo Router?"
-> See references/expo-router-loaders.md for route-level loaders (web, SDK 55+). For native, use React Query or fetch.
Limitations
Use this skill only when the task clearly matches its upstream product or API scope.
Verify commands, API behavior, pricing, quotas, credentials, and deployment effects against current official documentation before making changes.
Do not treat generated examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.