react-native-apikit
Version:
Modern API toolkit for React Native and Expo with automatic token management, smart response parsing, and built-in error handling
519 lines (403 loc) β’ 14.4 kB
Markdown
# 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
```sh
npm install react-native-apikit
# or
yarn add react-native-apikit
```
### 2. (Optional) For Axios engine
```sh
npm install axios
```
### 3. For Token Storage (Choose ONE based on your project)
#### For React Native CLI (Recommended)
```sh
npm install @react-native-async-storage/async-storage
```
#### For Expo projects only
```sh
expo install expo-secure-store
```
#### For Fastest Storage (MMKV)
```sh
npm install react-native-mmkv
```
**Note:**
- Use `@react-native-async-storage/async-storage` for React Native CLI projects
- Use `expo-secure-store` only for Expo projects
- Use `react-native-mmkv` for 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)
```tsx
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
```tsx
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
```tsx
const { get, data, loading, error } = useApi();
get('/users');
```
### POST request with body
```tsx
post('/login', { email, password });
```
### Custom headers, params, and error handling
```tsx
get('/profile', {
headers: { 'X-Custom': 'value' },
params: { lang: 'en' },
timeout: 5000,
});
```
### Switch to Axios engine
```tsx
configureApiKit({ engine: 'axios' });
```
### Use SecureStore for Expo
```tsx
configureApiKit({ tokenStorage: secureStoreToken });
```
### Use MMKV for Fastest Storage
```tsx
configureApiKit({ tokenStorage: mmkvToken });
```
### Custom token storage
```tsx
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:**
```js
// 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:**
```js
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 `configureApiKit` at app startup (App.js/ts).
- Use `useApi` in 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` (install `expo-secure-store`)
- **For Fastest Storage:** Use `mmkvToken` (install `react-native-mmkv`)
- Use Axios engine only if you need interceptors or advanced cancel tokens.
- Always handle `loading` and `error` states 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
```tsx
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
```tsx
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
```tsx
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
- [ApiKit GitHub](https://github.com/SamadK01/apikit)
- [React Native Docs](https://reactnative.dev/)
- [Expo Docs](https://docs.expo.dev/)
- [Axios](https://axios-http.com/)
- [MMKV](https://github.com/mrousavy/react-native-mmkv)
## π Use API Without Hook (Plain JS/Thunk)
You can now use the API outside React components (e.g., in thunks, services, or plain JS):
```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](https://github.com/mrousavy/react-native-mmkv) for ultra-fast, efficient token storage. Just use `mmkvToken` in your config:
```js
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)
```js
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)
```js
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)
```js
configureApiKit({ retry: 3 }); // Retries failed requests up to 3 times
// Or per-request:
get('/users', { timeout: 5000, /* ... */, });
```
### Cancelable Requests
```js
const { get } = useApi();
const { promise, cancel } = get('/users');
// To cancel:
cancel();
```
### Pagination (usePaginatedApi)
```js
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 hooks
- `cache`: Caching plugin (see above)
- `retry`: Number of retries (with exponential backoff)