react-native-apikit
v1.4.0
Published
Modern API toolkit for React Native and Expo with automatic token management, smart response parsing, and built-in error handling
Maintainers
Readme
ApiKit
🆕 What’s New in v1.4.0
- Global Interceptors: Pre-request, post-response, and error hooks for full control
- Caching: Plugin-based, with built-in in-memory cache (see below)
- Retry Logic: Exponential backoff, configurable per request or globally
- Cancelable Requests: All useApi methods now support cancellation
- Pagination: New usePaginatedApi hook for easy paginated data fetching
- Tighter TypeScript Typings: All new features are strongly typed for a great DX
Write once, request anywhere—no boilerplate, no confusion, just clean code.
ApiKit is the ultimate, modern API toolkit for React Native and Expo. It automates everything you repeat in API calls—loading, error, data states, token injection, smart response parsing, network status, timeout/cancel, global 401 handling, retry logic, and friendly error messages. Fetch is the default engine, but you can switch to Axios with one line. TypeScript-first, tree-shakable, minimal bundle size. For beginners and pros alike.
🚀 Why ApiKit?
- One hook, all power:
useApi()handles everything—no more manual state, try/catch, or header plumbing. - Fetch-first, Axios-compatible: Use the fastest native fetch, or switch to Axios (with interceptors/cancel tokens) instantly.
- Expo & React Native CLI: Works out-of-the-box in all RN/Expo projects (Android/iOS/Web).
- Automatic token management: Securely injects tokens from AsyncStorage, SecureStore, MMKV, or your own storage.
- Smart response parsing: Handles JSON, text, FormData, binary—no manual parsing needed.
- Network-aware: Detects offline/online, retries smartly, and gives user-friendly errors.
- Minimal, fast, and extensible: Tree-shakable, TypeScript-ready, and easy to extend.
✨ Features
- Single, readable hook:
useApi() - Built-in loading, error, data states
- Automatic token injection (AsyncStorage, SecureStore, MMKV, or custom)
- Smart response parsing (JSON, text, FormData, binary)
- Network status detection
- Timeout & cancel support
- Global 401 handling
- Retry logic
- Friendly error messages ("No Internet", "Server Error", validation, etc.)
- Fetch default, Axios optional (with interceptors/cancel tokens)
- TypeScript support, tree-shakable, minimal bundle size
- Expo & React Native CLI compatible
📦 Installation
1. Install ApiKit
npm install react-native-apikit
# or
yarn add react-native-apikit2. (Optional) For Axios engine
npm install axios3. For Token Storage (Choose ONE based on your project)
For React Native CLI (Recommended)
npm install @react-native-async-storage/async-storageFor Expo projects only
expo install expo-secure-storeFor Fastest Storage (MMKV)
npm install react-native-mmkvNote:
- Use
@react-native-async-storage/async-storagefor React Native CLI projects - Use
expo-secure-storeonly for Expo projects - Use
react-native-mmkvfor best performance (recommended for large apps) - ApiKit will show helpful warnings if the required storage dependency isn't installed
⚡️ Quick Start
1. Configure ApiKit (global setup)
import { configureApiKit, asyncStorageToken, secureStoreToken, mmkvToken } from 'react-native-apikit';
// For React Native CLI (recommended)
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: asyncStorageToken, // Use this for React Native CLI
engine: 'fetch', // or 'axios'
retry: 2, // auto-retry failed requests
timeout: 10000, // 10s timeout
onUnauthorized: () => {/* handle global 401 */},
});
// For Expo projects only
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: secureStoreToken, // Use this for Expo
engine: 'fetch',
retry: 2,
timeout: 10000,
onUnauthorized: () => {/* handle global 401 */},
});
// For Fastest Storage (MMKV)
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: mmkvToken, // Use this for best performance
engine: 'fetch',
retry: 2,
timeout: 10000,
onUnauthorized: () => {/* handle global 401 */},
});2. Use the useApi hook in your components
import { useApi } from 'react-native-apikit';
function UserList() {
const { get, post, loading, error, data } = useApi();
useEffect(() => {
get('/users');
}, []);
if (loading) return <ActivityIndicator />;
if (error) return <Text>{error.message}</Text>;
return <FlatList data={data} renderItem={...} />;
}🛠 Usage Examples
GET request
const { get, data, loading, error } = useApi();
get('/users');POST request with body
post('/login', { email, password });Custom headers, params, and error handling
get('/profile', {
headers: { 'X-Custom': 'value' },
params: { lang: 'en' },
timeout: 5000,
});Switch to Axios engine
configureApiKit({ engine: 'axios' });Use SecureStore for Expo
configureApiKit({ tokenStorage: secureStoreToken });Use MMKV for Fastest Storage
configureApiKit({ tokenStorage: mmkvToken });Custom token storage
const myStorage = {
getToken: async () => ..., setToken: async (t) => ..., removeToken: async () => ...
};
configureApiKit({ tokenStorage: myStorage });🔒 Token Management
- Automatic: All requests include your token (Bearer) if available.
- Storage options:
asyncStorageToken(React Native CLI - recommended)secureStoreToken(Expo projects only)mmkvToken(Fastest, recommended for large apps)- Custom storage implementation
- Set/Remove token:
// For React Native CLI await asyncStorageToken.setToken('your-token'); await asyncStorageToken.removeToken(); // For Expo await secureStoreToken.setToken('your-token'); await secureStoreToken.removeToken(); // For MMKV await mmkvToken.setToken('your-token'); await mmkvToken.removeToken();
🌐 Network, Timeout, Retry, Cancel
- Network status: Detects offline/online, returns friendly errors.
- Timeout: Set per-request or globally.
- Retry: Auto-retry failed requests (configurable).
- Cancel: Cancel requests with AbortController (fetch) or cancel tokens (axios).
🧩 Advanced: Custom Engine & Extensibility
- Custom engine:
const myEngine = { request: async (config) => { /* ... */ } }; configureApiKit({ engine: myEngine }); - Interceptors (Axios): Use axios as usual, all interceptors/cancel tokens work.
- Global 401: Handle unauthorized globally with
onUnauthorized.
🆚 ApiKit vs Others
| Feature | ApiKit | react-query | swr | axios | fetch | |------------------------|:------:|:-----------:|:---:|:-----:|:-----:| | React Native/Expo | ✅ | ⚠️ | ⚠️ | ✅ | ✅ | | useApi hook | ✅ | ❌ | ❌ | ❌ | ❌ | | Built-in loading/error | ✅ | ✅ | ✅ | ❌ | ❌ | | Token injection | ✅ | ❌ | ❌ | ❌ | ❌ | | Engine switch (fetch/axios) | ✅ | ❌ | ❌ | ✅ | ✅ | | Network/timeout/cancel | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | | Retry logic | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | | Global 401 | ✅ | ❌ | ❌ | ❌ | ❌ | | Tree-shakable/minimal | ✅ | ❌ | ❌ | ❌ | ✅ | | TypeScript-first | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
🏆 Best Practices
- Use
configureApiKitat app startup (App.js/ts). - Use
useApiin every screen/component for clean, isolated API logic. - For React Native CLI: Use
asyncStorageToken(install@react-native-async-storage/async-storage) - For Expo: Use
secureStoreToken(installexpo-secure-store) - For Fastest Storage: Use
mmkvToken(installreact-native-mmkv) - Use Axios engine only if you need interceptors or advanced cancel tokens.
- Always handle
loadinganderrorstates in UI.
🔄 Migrating from Axios/Fetch/Other Hooks
- Replace all manual fetch/axios calls with
useApi().get/post/put/patch/del. - Remove manual state, try/catch, and token/header plumbing.
- Use ApiKit's built-in error and loading states.
🧑💻 Real-World Examples
React Native CLI Example
import { configureApiKit, useApi, asyncStorageToken } from 'react-native-apikit';
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: asyncStorageToken, // For React Native CLI
engine: 'fetch',
});
export default function App() {
const { get, post, loading, error, data } = useApi();
useEffect(() => {
get('/me');
}, []);
// ...render UI
}Expo Example
import { configureApiKit, useApi, secureStoreToken } from 'react-native-apikit';
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: secureStoreToken, // For Expo only
engine: 'fetch',
});
export default function App() {
const { get, post, loading, error, data } = useApi();
useEffect(() => {
get('/me');
}, []);
// ...render UI
}MMKV Example
import { configureApiKit, useApi, mmkvToken } from 'react-native-apikit';
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: mmkvToken, // For best performance
engine: 'fetch',
});
export default function App() {
const { get, post, loading, error, data } = useApi();
useEffect(() => {
get('/me');
}, []);
// ...render UI
}📚 API Reference
configureApiKit(config)
Set global config (baseUrl, engine, tokenStorage, retry, timeout, onUnauthorized, headers).
useApi()
Returns { get, post, put, patch, del, loading, error, data, reset }.
Engines
fetchEngine(default)axiosEngine(optional, install axios)
Token Storage
asyncStorageToken(React Native CLI - recommended)secureStoreToken(Expo projects only)mmkvToken(Fastest, recommended for large apps)- Custom:
{ getToken, setToken, removeToken }
📲 Platform Support
- Android: 100% compatible (Expo & RN CLI)
- iOS: 100% compatible (Expo & RN CLI)
- Web: Works with fetch engine (limited features)
📝 License
MIT
🙋 FAQ
Q: Can I use ApiKit in Expo Go?
A: Yes! Use secureStoreToken for token storage and install expo-secure-store.
Q: Can I use ApiKit in React Native CLI?
A: Yes! Use asyncStorageToken for token storage and install @react-native-async-storage/async-storage.
Q: Can I use ApiKit with MMKV?
A: Yes! Use mmkvToken for fastest storage and install react-native-mmkv.
Q: How do I switch to Axios?
A: configureApiKit({ engine: 'axios' }) and install axios.
Q: How do I handle file uploads?
A: Pass FormData as data in your request.
Q: How do I add global headers?
A: Use headers in configureApiKit.
Q: How do I catch validation errors?
A: All errors are parsed and available in the error object from useApi.
Q: What if I don't install the storage dependency? A: ApiKit will show helpful console warnings and return null for token operations.
🤝 Contributing
Pull requests, issues, and suggestions welcome!
🔗 Links
🆕 Use API Without Hook (Plain JS/Thunk)
You can now use the API outside React components (e.g., in thunks, services, or plain JS):
import { apiClient } from 'react-native-apikit';
// GET request
const { data, error } = await apiClient.get('/users');
// POST request
const { data, error } = await apiClient.post('/login', { email, password });
// Full control
const { data, error, status } = await apiClient.request({
method: 'PUT',
url: '/profile',
data: { name: 'John' },
});🚀 MMKV Support (Recommended)
ApiKit now supports MMKV for ultra-fast, efficient token storage. Just use mmkvToken in your config:
import { configureApiKit, mmkvToken } from 'react-native-apikit';
configureApiKit({
baseUrl: 'https://api.example.com',
tokenStorage: mmkvToken, // Fastest storage
engine: 'fetch',
});MMKV is highly recommended for large apps or those needing best performance.
🧩 Advanced Usage & New Features
Global Interceptors (Pre-request, Post-response, Error)
configureApiKit({
...,
onRequest: async (config) => {
// Modify config before request
return config;
},
onResponse: async (response) => {
// Inspect/modify response
return response;
},
onError: async (error) => {
// Global error handling
return error;
},
});Caching (with Plugin System)
import { configureApiKit } from 'react-native-apikit';
import { memoryCache } from 'react-native-apikit/dist/storage/asyncStorage';
configureApiKit({
...,
cache: memoryCache, // Built-in in-memory cache
});
// GET requests are cached automatically (default 1 min)
get('/users');
// Custom cache plugin example:
const myCache = {
get: async (key) => ..., set: async (key, value, ttl) => ..., clear: async (key) => ...
};
configureApiKit({ cache: myCache });Retry Logic (Exponential Backoff)
configureApiKit({ retry: 3 }); // Retries failed requests up to 3 times
// Or per-request:
get('/users', { timeout: 5000, /* ... */, });Cancelable Requests
const { get } = useApi();
const { promise, cancel } = get('/users');
// To cancel:
cancel();Pagination (usePaginatedApi)
import { usePaginatedApi } from 'react-native-apikit';
function UserList() {
const { data, loading, error, page, hasMore, nextPage, prevPage, reset } = usePaginatedApi('/users', {
pageSize: 20,
params: { status: 'active' },
});
// ...render paginated list, call nextPage() to load more
}🔎 Quick Reference: New Config Options
onRequest,onResponse,onError: Interceptor hookscache: Caching plugin (see above)retry: Number of retries (with exponential backoff)
