fetch: built-in, đủ dùng cho 80% case. Yếu điểm: không timeout default (phải dùng AbortController), không retry, parse JSON cần .json() rời.
axios: API gọn hơn, transformer built-in, interceptor cho auth header và refresh token, timeout config dễ.
const api = axios.create({ baseURL: 'https://api.example.com', timeout: 10_000 })
api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`
return config
})Retry / backoff: dùng axios-retry hoặc viết qua TanStack Query (built-in retry: 3, retryDelay: exponential).
Offline detection: @react-native-community/netinfo:
import NetInfo from '@react-native-community/netinfo'
NetInfo.addEventListener((state) => console.log(state.isConnected, state.type))Pattern thường thấy: wrap toàn app trong NetInfoProvider → expose isOnline. TanStack Query onlineManager.setEventListener để pause query khi offline. Hiển thị banner "You are offline" toàn cục. Mutation queue: khi offline, lưu request vào MMKV; khi online lại, replay.
RN-specific gotcha: trên iOS simulator, NetInfo.fetch().isConnected có thể trả true ngay cả khi không có internet thật — luôn test trên device.
fetch: built-in, fine for ~80% of cases. Weaknesses: no default timeout (use AbortController), no retry, JSON parse requires a separate .json() call.
axios: nicer API, built-in transformers, interceptors for auth headers and refresh tokens, easy timeout config.
const api = axios.create({ baseURL: 'https://api.example.com', timeout: 10_000 })
api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`
return config
})Retry / backoff: use axios-retry or rely on TanStack Query (built-in retry: 3, retryDelay: exponential).
Offline detection: @react-native-community/netinfo:
import NetInfo from '@react-native-community/netinfo'
NetInfo.addEventListener((state) => console.log(state.isConnected, state.type))Common pattern: wrap the app in a NetInfoProvider exposing isOnline. Hook onlineManager.setEventListener from TanStack Query to pause queries while offline. Show a global "You are offline" banner. Mutation queue: while offline, persist requests to MMKV; on reconnect replay them.
RN-specific gotcha: on the iOS simulator, NetInfo.fetch().isConnected can return true even without real internet — always test on a real device.