create-fetch-hooks
Version:
A simple and powerful custom React hook (useApi) that simplifies API requests with automatic loading and error states. Ideal for clean and maintainable data fetching in React components.
226 lines (170 loc) • 6.61 kB
Markdown
<img src="https://raw.githubusercontent.com/ashrafbinahmad/create-fetch-hooks/refs/heads/main/images/logo.png" alt="Logo" width="70"/> <br/>
# 🎞 Create Fetch Hooks – Custom API Hook Factory
Easily generate `React` hooks and HTTP methods (`GET`, `POST`, `PUT`, `DELETE`) with unified error handling, headers support, response tracking, token refresh, and enhanced developer experience.
## ✨ What is this?
This utility provides:
✅ React Hooks: `useGet`, `usePost`, `usePut`, `useDelete`
✅ Direct HTTP methods: `httpClient.get`, `httpClient.post`, `httpClient.put`, `httpClient.del`
✅ Cache management with `FetchCacheProvider`
✅ Automatic token refresh with customizable logic
It simplifies working with REST APIs in a type-safe, scalable way with built-in support for authentication and caching.
## 🚀 Quick Setup
Initialize the hooks and HTTP client with a base URL and optional configuration, including token refresh logic:
```ts
export const {
useGet,
useDelete,
usePost,
usePut,
httpClient,
FetchCacheProvider,
} = createFetchHooks(
"http://localhost:3000/", // API base url
//Optional - Required if you want auto refresh tokens:
{
accessTokenLocalStorageKey: "accessToken",
callRefreshToken() {
return {
on: [403], // The response code to be tracked to refresh token
body: { refreshToken: localStorage.getItem("refreshToken") || "" }, // refresh token body
endpoint: "/refresh", // The refresh token end point
saveAccessTokenFromResponse: async function (res) {
localStorage.setItem("accessToken", res?.accessToken);
},
};
},
}
);
```
Wrap your app with `FetchCacheProvider` to enable caching:
```tsx
// Optional - Required if you want cache (eg: Need not to wait if already loaded when returning to the page, it will load from cache)
import { FetchCacheProvider } from "create-fetch-hooks";
function App() {
return (
<FetchCacheProvider>
<YourApp />
</FetchCacheProvider>
);
}
```
## 💡 Why use this over other libraries?
| Feature | create-fetch-hooks | Axios | React Query |
|-------------------------------------|--------------------|-------|-------------|
| Fully typed with generics | ✅ | ⚠️ | ✅ |
| React-friendly hooks | ✅ | ❌ | ✅ |
| Custom `onResponse` tracking | ✅ | ❌ | ❌ |
| Optional debounce for `useGet` | ✅ | ❌ | ⚠️ Plugin |
| Unified header injection | ✅ | ⚠️ | ⚠️ |
| Minimalistic, no extra deps | ✅ | ❌ | ❌ |
| Convert to `FormData` in `POST/PUT` | ✅ | ❌ | ⚠️ Manual |
| Works without any context provider - Required if caching needed | ✅ | ❌ | ❌ |
| Token refresh support | ✅ | ⚠️ | ⚠️ Manual |
| Cache management with `FetchCacheProvider` | ✅ | ❌ | ✅ |
## 📦 Installation
```bash
npm i create-fetch-hooks
```
## 🔗 Importing
```ts
import { createFetchHooks } from "create-fetch-hooks";
```
## 🧙♂️ Hook Return Types
| Hook | Return |
|-------------|------------------------------------|
| `useGet` | `{ data, error, loading, reload }` |
| `usePost` | `{ error, loading, postData }` |
| `usePut` | `{ error, loading, putData }` |
| `useDelete` | `{ error, loading, deleteData }` |
## 🌍 Real-World Usage Example
**📁 /hooks/api.ts**
```ts
import { createFetchHooks } from "create-fetch-hooks";
export const {
useGet,
usePost,
usePut,
useDelete,
httpClient,
FetchCacheProvider,
} = createFetchHooks("https://api.example.com", {
accessTokenLocalStorageKey: "accessToken",
callRefreshToken() {
return {
on: [403],
body: { refreshToken: localStorage.getItem("refreshToken") || "" },
endpoint: "/refresh",
saveAccessTokenFromResponse: async (res) => {
localStorage.setItem("accessToken", res?.accessToken);
},
};
},
onResponse(url, endpoint, responseCode) {
if (endpoint === "/me" && responseCode === 401) {
localStorage.removeItem("accessToken");
window.location.href = "/login";
}
},
});
```
**📁 /components/UserList.tsx**
```tsx
import { useGet } from "../hooks/api";
interface User {
id: number;
name: string;
}
const UserList = () => {
const { data: users, loading, error, reload } = useGet<User[]>("/users");
if (loading) return <p>Loading...</p>;
if (error) return <p>Error occurred: {error.message}</p>;
return (
<ul>
{users?.map((user) => (
<li key={user.id}>{user.name}</li>
))}
<button onClick={reload}>Reload</button>
</ul>
);
};
export default UserList;
```
**📁 /App.tsx**
```tsx
import { FetchCacheProvider } from "../hooks/api";
import UserList from "./components/UserList";
function App() {
return (
<FetchCacheProvider>
<UserList />
</FetchCacheProvider>
);
}
export default App;
```
## 📜 Docs
All options and return types are strongly typed with TypeScript. Key configuration options include:
- `setHeaders`: Function to dynamically generate headers for each request.
- `accessTokenLocalStorageKey`: Key for retrieving access token from localStorage.
- `callRefreshToken`: Configures token refresh logic, including response codes, endpoint, body, and token storage.
- `onResponse`: Callback for handling responses globally.
- `onSuccess`, `onError`, `onResponseGot`: Callbacks for specific hooks.
- `convertToFormData`, `removeIfValueIsNullOrUndefined`: Options for POST/PUT data handling.
- `debounce`, `dontRequestIfUrlIncludeNullOrUndefined`: Options for GET requests.
Check the source code and full examples on GitHub for detailed usage.
## 📌 Links
- 🔗 NPM: [create-fetch-hooks](https://www.npmjs.com/package/create-fetch-hooks)
- 🐙 GitHub: [ashrafbinahmad/create-fetch-hooks](https://github.com/ashrafbinahmad/create-fetch-hooks)
If you find this package helpful, **please ⭐ the repo on GitHub!** It really helps! 🙏
## 📜 License
MIT