JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 19
  • Score
    100M100P100Q88692F
  • License MIT

A smart React data-fetching hook with caching, retries, TTL, and auto token refresh.

Package Exports

  • use-fetch-smart
  • use-fetch-smart/dist/index.js
  • use-fetch-smart/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (use-fetch-smart) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

use-fetch-smart

A smart React data-fetching library with caching, TTL, retry logic, token auto-refresh, and simple mutation hooks.

✨ Why use-fetch-smart?

Fetching data in React apps often ends up with repetitive boilerplate: loading states, error handling, caching, token refresh logic, retry logic, etc. use-fetch-smart is designed to replace that boilerplate with a clean, declarative interface and handle many of the common patterns for you. Key benefits:

  • Smart GET hook with caching + Time-to-Live (TTL) expiry
  • Mutation hooks (POST / PUT / DELETE) with minimal setup
  • Automatic retry logic (for network failures or 5xx responses)
  • Automatic token refresh when a 401 occurs, and request replay
  • Single global provider to configure your fetch-layer (base URL, token, retry limits)
  • Devtools panel to inspect cache, TTL, retry counts, etc
  • TypeScript first: full typing support out of the box

In short: stop re-writing loading/error/spinner logic, stop manually managing cache/invalidations, stop writing token refresh logic over and over. Let the library handle the data layer; you focus on your UI and domain logic.


🚀 Installation

npm install use-fetch-smart
# or
yarn add use-fetch-smart

🧩 Provider Setup

Wrap your React app (or the high-level section of it) with the FetchSmartProvider to configure the global data‐fetching environment. Example:

import React from 'react';
import { FetchSmartProvider, FetchSmartDevtools } from 'use-fetch-smart';

const refreshToken = async () => {
  // Your logic to request a new token when current one expires (401).
  return await fetch('/auth/refresh')
    .then(r => r.json())
    .then(x => x.token)
    .catch(() => null);
};

const AppWrapper = () => (
  <FetchSmartProvider
    config={{
      baseURL: 'https://api.example.com',
      token: 'initial-token-if-known',
      refreshToken,           // function to call on 401
      retryLimit: 3,          // global retry limit for failed requests
      // you may add other axios-style config if supported
    }}
  >
    <YourApp />
    <FetchSmartDevtools />
  </FetchSmartProvider>
);

export default AppWrapper;

What this config does:

  • baseURL: the base URL for your API endpoints
  • token: initial token (if you already have one in memory/storage)
  • refreshToken: a function returning a new token (or null if refresh fails) — this will be automatically used when a request gets a 401
  • retryLimit: number of retry attempts for network/server errors

Once the provider is set up, all hooks (useGetSmart, usePostSmart, etc.) will automatically use this configured instance.


📊 Fetching Data — useGetSmart

import { useGetSmart } from 'use-fetch-smart';

const Users = () => {
  const { data, loading, error, refetch } = useGetSmart<User[]>('/users', {
    cacheTimeMs: 2 * 60 * 1000,  
    persist:true
  });
---

# use-fetch-smart

> A lightweight, TypeScript-first React data-fetching layer with built-in caching (memory + optional IndexedDB), TTL, retries, and automatic token refresh.

[![npm version](https://img.shields.io/npm/v/use-fetch-smart.svg)](https://www.npmjs.com/package/use-fetch-smart) [![GitHub Repo](https://img.shields.io/badge/GitHub-Repository-black?logo=github)](https://github.com/zaidshaikh2811/use-fetch-smart)

---

## Install

```bash
npm install use-fetch-smart
# or
yarn add use-fetch-smart

This package uses axios and includes optional IndexedDB persistence via idb-keyval for larger or persistent caches.

Quick Start

Wrap your app with FetchSmartProvider to configure baseURL, token handling, and retry behavior.

import React from 'react';
import { FetchSmartProvider, FetchSmartDevtools } from 'use-fetch-smart';

const refreshToken = async () => {
  // Example: call your refresh endpoint and return the new token string or `null`.
  const r = await fetch('/auth/refresh');
  if (!r.ok) return null;
  const json = await r.json();
  return json.token;
};

export default function AppRoot() {
  return (
    <FetchSmartProvider config={{ baseURL: 'http://localhost:4000', retryLimit: 3, refreshToken }}>
      <App />
      <FetchSmartDevtools />
    </FetchSmartProvider>
  );
}

What you get

  • useGetSmart — GET hook with instant cache reads, TTL and refetch.
  • usePostSmart, usePutSmart, useDeleteSmart — simple mutation hooks with loading/error states.
  • Layered cache: fast in-memory cache plus optional persistent IndexedDB via cacheDriver.
  • Automatic token refresh and request replay on 401 when a refreshToken function is provided.
  • Automatic retries for network errors and 5xx responses with backoff.
  • Devtools component to inspect cache keys, TTL, and request history.

Hooks — quick examples

useGetSmart

import { useGetSmart } from 'use-fetch-smart';

function Users() {
  const { data, loading, error, refetch } = useGetSmart('/users', { cacheTimeMs: 60_000, persist: false });

  if (loading) return <div>Loading…</div>;
  if (error) return <div>Error</div>;

  return (
    <div>
      <button onClick={refetch}>Refresh</button>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

usePostSmart

import { usePostSmart } from 'use-fetch-smart';

function CreateUser() {
  const { mutate, loading } = usePostSmart('/users');

  return (
    <button onClick={() => mutate({ name: 'Zaid' })} disabled={loading}>
      {loading ? 'Saving…' : 'Create User'}
    </button>
  );
}

Cache & Persistence

The library uses a layered cache:

  • memoryCache — fast in-memory store for instant reads
  • indexedDBCache (via idb-keyval) — optional persistence for larger or long-lived caches
  • cacheDriver — unified API to get/set/delete and to opt into persistence per entry (persist: true)

Use cacheTimeMs and persist options to control TTL and storage mode.

Example: store a GET response in IndexedDB for 10 minutes:

useGetSmart('/settings', { cacheTimeMs: 10 * 60_000, persist: true });

Advanced usage & utilities

You can use lower-level utilities exported by the package for advanced scenarios:

import { cacheManager, axiosInstance } from 'use-fetch-smart';

// clear a specific cache key
cacheManager.clear('GET_/users');

// use the provided axios instance for non-hook requests
axiosInstance.get('/status');

If you need to build a custom axios instance, the package exposes a createSmartAxios helper in the source files (see src/axiosInstance.ts).


Examples

This repo includes examples/ (Express backend + Vite React frontend) demonstrating provider setup and hooks. See examples/README.md for setup and run commands.


Optimizations & Best Practices

  • Tune cacheTimeMs per endpoint (short TTL for live lists, longer TTL for stable resources).
  • Use persist: true only for expensive-to-fetch or important data (e.g., user preferences).
  • After mutations, call refetch() on related queries or use cacheManager.clear() to invalidate.
  • Keep retryLimit low for mutation endpoints to avoid duplicate side effects; rely on server idempotency where possible.
  • Gate FetchSmartDevtools behind NODE_ENV !== 'production' during builds.

Troubleshooting

  • Stale data: check TTL and whether you used persist — call refetch() or clear the key via cacheManager.
  • Repeated 401 refreshes: ensure your refreshToken returns null on failure and your backend isn't returning 401 for all requests.
  • IndexedDB errors: browser may deny access in some environments; cacheDriver falls back to memory when IndexedDB fails.

Package & Version

  • Current package version: 1.0.10 (see package.json).
  • Type definitions included and dist/ is published via the files entry.

License

MIT © 2025


If you'd like, I can also:

  • Add a short "Examples" section to the main README.md linking to examples/ (I can apply this patch now).
  • Scaffold examples/backend and examples/frontend files into the repo and add npm scripts to start them.

Suggested commit message:

docs(npm-readme): update README.npm.md to reflect cache/persistence and examples

  • or integrate a custom invalidation logic: e.g., clear cache key manually using cacheManager (if your library exposes it)
  • Example: after creating a new user, you might refetch /users.

3. Token handling

Since the library handles auto‐refresh for 401s:

  • Ensure your refreshToken logic returns the new token (and persists it if you store it)
  • On refreshing token, subsequent calls will use the new token automatically
  • Edge case: if refresh fails (returns null), you may want to redirect to login/logout.

4. Minimise over-fetching

  • Use skip or conditional fetches (if supported) when component shouldn’t fetch on mount (e.g., waiting user input)
  • Use dependencies (if supported) to fetch only when necessary.

5. Server-side data and hydration (if e.g. using Next.js)

  • If you’re using SSR/SSG, you may want to pre‐fetch data and hydrate the cache on the client. Check if your library supports that.
  • While this library focuses on client‐side React, you may integrate with SSR setups by using initial cache values or disabling caching on initial load.

6. Bundling & tree-shaking

  • Since this library is lightweight and TypeScript‐first, ensure your bundler (e.g., Webpack/Rollup) tree-shakes unused parts.
  • Avoid importing full library if you only use one hook. (i.e., import { useGetSmart } from 'use-fetch-smart').
  • Monitor bundle size (e.g., via bundlephobia).

7. Error boundaries and global error handling

  • While hooks provide error state, you might use a global error boundary or React error boundary to catch unexpected exceptions.
  • Use logging (e.g., Sentry) for network/fetch errors to track in production.

📋 API Reference

FetchSmartProvider

Props:

  • config: { baseURL: string; token?: string; refreshToken?: () => Promise<string | null>; retryLimit?: number; /* plus any axios config like headers, timeout etc */ }
  • Children: your React tree
  • Optionally include <FetchSmartDevtools /> as a child.

Hooks

useGetSmart<T>(url: string, options?: { cacheTimeMs?: number; skip?: boolean; dependencies?: any[]; /* other possible options */ }) => { data: T | undefined; loading: boolean; error: Error | null; refetch: () => Promise<void> }

usePostSmart<T, P>(url: string) => { mutate: (payload: P) => Promise<T>; loading: boolean; error: Error | null }

usePutSmart<T, P>(url: string) => { mutate: (payload: P) => Promise<T>; loading: boolean; error: Error | null }

useDeleteSmart<T>(url: string) => { mutate: () => Promise<T>; loading: boolean; error: Error | null }

Other exports

  • axiosInstance — underlying Axios instance (for advanced use)
  • cacheManager — to programmatically inspect/clear cache (if supported)
  • setGlobalToken — to set token globally outside hooks (if you update token elsewhere)

(Make sure to list any more utility methods your library provides.)


🧠 Why This Library Is Better

  • Less boilerplate: you get data, loading, error, refetch in one line instead of writing your own state and effect every time.
  • Caching built-in: You don’t need separate libraries for caching; TTL is built in and automatic.
  • Retry logic: Out‐of‐the-box support for retrying failed requests, helping stability in flaky network conditions.
  • Token refresh built-in: No need to write the same “if 401 then refresh token and retry” logic everywhere — the provider handles it.
  • Single global config: You configure once (base URL, token, retry, etc) and all hooks inherit it.
  • Devtools for visibility: Monitoring cache, TTL, retries, status codes gives you better insight during development.
  • TypeScript support: Helps with correctness, developer experience and future maintenance.
  • Focused & lightweight: Not a full state-management or data layer library (like React Query), but a simpler, focused solution for fetch + cache + retry + token. If you don’t need all features of a heavier library this may be a perfect fit.

🧪 Example Full Workflow

// index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { FetchSmartProvider, FetchSmartDevtools } from 'use-fetch-smart';

const refreshToken = async () => {
  const result = await fetch('/auth/refresh').then(r => r.json());
  if (result.token) {
    return result.token;
  }
  return null;
};

ReactDOM.render(
  <FetchSmartProvider config={{ baseURL: 'https://api.myapp.com', token: localStorage.getItem('token') ?? undefined, refreshToken, retryLimit: 2 }}>
    <App />
    <FetchSmartDevtools />
  </FetchSmartProvider>,
  document.getElementById('root'),
);

// App.tsx
import React from 'react';
import { useGetSmart } from 'use-fetch-smart';

const Dashboard = () => {
  const { data: users, loading, error, refetch } = useGetSmart<User[]>('/users', { cacheTimeMs: 5 * 60 * 1000 });

  if (loading) return <div>Loading users …</div>;
  if (error) return <div>Error loading users: {error.message}</div>;

  return (
    <div>
      <h1>Users</h1>
      <button onClick={refetch}>Refresh</button>
      <ul>
        {users?.map(u => <li key={u.id}>{u.name}</li>)}
      </ul>
    </div>
  );
};

export default Dashboard;

📦 Package Details & Stability

  • Version: (update to latest)
  • TypeScript definitions included
  • MIT License
  • Compatible with React 17+ (verify your supported versions)
  • Lightweight bundle size (check on bundlephobia or similar)

👥 Contributing

If you’d like to contribute:

  • Fork the repository
  • Create a feature branch (git checkout -b feature/my-feature)
  • Write tests where applicable
  • Follow the code style in the repo
  • Submit a pull request
  • Issues and feature suggestions are welcome

📝 Changelog

Please refer to CHANGELOG.md in the repo for full version history and breaking changes.


🎉 Thank You

If you like use-fetch-smart, please star the GitHub repo — your support helps a lot ❤️ Happy fetching.



✅ Checklist for You

  • Update version number and npm badge if needed
  • Add links/badges for npm, bundle size, CI, license
  • If there are additional options for hooks (e.g., skip, dependencies etc), document them clearly
  • Provide example images or gifs (if you have) for cache hits, retry logic, token refresh, devtools
  • Provide a section for migration (if you are replacing an older version)
  • Ensure the README is published with the package (npm will show it)