npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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

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-apikit

2. (Optional) For Axios engine

npm install axios

3. For Token Storage (Choose ONE based on your project)

For React Native CLI (Recommended)

npm install @react-native-async-storage/async-storage

For Expo projects only

expo install expo-secure-store

For Fastest Storage (MMKV)

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)

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 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

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 hooks
  • cache: Caching plugin (see above)
  • retry: Number of retries (with exponential backoff)