{"id":18055671,"url":"https://github.com/aymericzip/api-refetch","last_synced_at":"2025-04-11T01:52:25.069Z","repository":{"id":260152456,"uuid":"880471203","full_name":"aymericzip/api-refetch","owner":"aymericzip","description":"Alternative to SWC or react-query. Hook that store your API calls and provide states as isLoading, isFetched, data, error. Allow to instantly fetch the API when the hook is mounted. Provide retry and revalidation options.","archived":false,"fork":false,"pushed_at":"2025-01-21T19:30:01.000Z","size":95,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T01:52:16.970Z","etag":null,"topics":["api","async","autofetch","cache","data","fetch","loading","react-query","retry","revalidate","session-storage","state","store","swr","zustand"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aymericzip.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-29T19:33:38.000Z","updated_at":"2025-01-21T19:30:05.000Z","dependencies_parsed_at":"2025-01-13T22:19:29.121Z","dependency_job_id":"f0065374-5b7f-404c-9463-ddd303463c2e","html_url":"https://github.com/aymericzip/api-refetch","commit_stats":null,"previous_names":["aymericzip/api-refetch"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aymericzip%2Fapi-refetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aymericzip%2Fapi-refetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aymericzip%2Fapi-refetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aymericzip%2Fapi-refetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aymericzip","download_url":"https://codeload.github.com/aymericzip/api-refetch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248328108,"owners_count":21085258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","async","autofetch","cache","data","fetch","loading","react-query","retry","revalidate","session-storage","state","store","swr","zustand"],"created_at":"2024-10-31T01:11:06.849Z","updated_at":"2025-04-11T01:52:25.061Z","avatar_url":"https://github.com/aymericzip.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# api-refetch\n\n`api-refetch` is a React hook library designed to simplify the management of asynchronous API requests within React applications. This library provides a powerful and flexible hook, `useAsync`, that handles fetching, caching, retries, and state management of asynchronous operations.\n\n## Features\n\n- **Easy to use**: Integrate asynchronous data fetching into your components with minimal boilerplate.\n- **State management**: Automatically manages loading, error, success, and fetched states.\n- **Storage**: Built-in support for storing and retrieving data in session storage.\n- **Caching**: Optional caching of requests to improve performance and reduce server load.\n- **Retry Logic**: Configurable retry mechanism for failed requests.\n- **Revalidation**: Supports automatic revalidation of data to keep the UI up to date.\n- **Parallel Component Mount Fetching**: api-refetch provides a mechanism to handle parallel component mount fetching, ensuring that only one fetch request is initiated at a time, regardless of the number of components mounting simultaneously.\n- **Customizable**: Extensive options to tailor the behavior of the hook to your needs.\n\n## Installation\n\nInstall the package via npm:\n\n```bash\nnpm install api-refetch\n```\n\nusing pnpm:\n\n```bash\npnpm add api-refetch\n```\n\nor using yarn:\n\n```bash\nyarn add api-refetch\n```\n\n## Usage\n\nHere's a simple example of how to use `api-refetch` to fetch user data from an API:\n\n### Setting up the Async Function\n\nFirst, define the asynchronous function that fetches your data. For example, fetching user data:\n\n```javascript\nconst fetchUserData = async (userId) =\u003e {\n  const response = await fetch(`/api/users/${userId}`);\n  if (!response.ok) {\n    throw new Error(\"Failed to fetch\");\n  }\n  return await response.json();\n};\n```\n\n### Add the provider in your application\n\nAdd the `RefetchProvider` to your application:\n\n```javascript\nimport { AsyncStateProvider } from \"api-refetch\";\n\nfunction App() {\n  return (\n    \u003cAsyncStateProvider\u003e\n      \u003cUserDetails userId={1} /\u003e\n    \u003c/AsyncStateProvider\u003e\n  );\n}\n```\n\n\u003e If you don't want to use the provider, you can use the `useAsync` hook from the `api-refetch/zustand` package directly.\n\u003e `useAsync` from `api-refetch/zustand` offers the same API as useAsync from api-refetch. The latter allows for a simpler setup. However, the store based on Zustand can sometimes be less optimized, as it may cause unwanted re-renders or, conversely, fail to re-render state changes.\n\u003e Therefore, it is generally preferable to stay within React's context.\n\n### Using the `useAsync` Hook\n\nNow, use the `useAsync` hook in your component:\n\n```javascript\nimport { useAsync } from \"api-refetch\";\n\nconst UserDetails = ({ userId }) =\u003e {\n  const { isLoading, data, error, revalidate, setData } = useAsync(\n    \"userDetails\",\n    () =\u003e fetchUserData(userId),\n    {\n      enable: true, // enable the hook\n      cache: true, // cache the API call result using zustand\n      store: true, // store the API call result in the session storage\n      retryLimit: 3, // retry 3 times if the API call fails\n      retryTime: 10 * 1000, // wait 10 seconds before retrying\n      autoFetch: true, // auto fetch the API call when the component is mounted\n      revalidation: true, // enable revalidation\n      revalidateTime: 5 * 60 * 1000, // revalidate every 5 minutes\n      isInvalidated: false, // determine if the data is invalidated and should be refetched\n      invalidateQueries: [\"user\"], // invalidate other queries when the data is updated\n      updateQueries: [\"user\"], // set other queries data when the data is updated\n      onSuccess: (data) =\u003e console.log(\"User data fetched successfully:\", data),\n      onError: (error) =\u003e console.error(\"Error fetching user data:\", error),\n    }\n  );\n\n  if (isLoading) return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  if (error) return \u003cdiv\u003eError: {error}\u003c/div\u003e;\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003e{data.name}\u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e revalidate()}\u003eRefresh\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setData(null)}\u003eClear\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n### Using the `useAsyncWrapper` Hook\n\nThe `useAsyncWrapper` hook is a convenient way to define a custom hook that wraps an asynchronous function. It simplifies the process of declaring and using the `useAsync` hook in your components.\n\nHere's an example of how to use the `useAsyncWrapper` hook to define a custom hook for fetching user data:\n\n```javascript\nimport { useAsyncWrapper } from \"api-refetch\";\n\nconst fetchUserData = async (userId) =\u003e {\n  const response = await fetch(`/api/users/${userId}`);\n  if (!response.ok) {\n    throw new Error(\"Failed to fetch\");\n  }\n  return await response.json();\n};\n\nconst useUserDetails = useAsyncWrapper(\"userDetails\", fetchUserData, {\n  // Additional options for the useAsync hook\n  autoFetch: true,\n});\n```\n\nNow, you can use the `useUserDetails` hook in your components:\n\n```javascript\nimport { useAsync } from \"api-refetch\";\n\nconst UserDetails = ({ userId }) =\u003e {\n  const { isLoading, data, error, revalidate, setData } =\n    useAsyncWrapper(userId);\n\n  if (isLoading) return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  if (error) return \u003cdiv\u003eError: {error}\u003c/div\u003e;\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003e{data.name}\u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e revalidate()}\u003eRefresh\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setData(null)}\u003eClear\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n## Merging hooks options\n\nYou can merge hooks options to make your code more readable and maintainable. For example, you can create a custom hook to handle error logging and toast notifications, and another hook to enable authentication. Here's how you can do it:\n\n```typescript\n/**\n *  Hook to handle error logging and toast notifications\n */\nconst useErrorHandling = \u003cT extends UseAsyncOptions\u003cany\u003e\u003e(options: T): T =\u003e {\n  const { toast } = useToast();\n\n  return {\n    ...options,\n    onError: (errorMessage) =\u003e {\n      const error = JSON.parse(errorMessage);\n      toast({\n        title: error.code ?? \"Error\",\n        description: error.message ?? \"An error occurred\",\n        variant: \"error\",\n      });\n      options.onError?.(errorMessage);\n    },\n  };\n};\n\n/**\n * Hook to enable authentication\n */\nconst useAuthEnable = \u003cT extends UseAsyncOptions\u003cany\u003e\u003e(options: T): T =\u003e {\n  const { csrfToken, oAuth2AccessToken } = useAuth();\n\n  return {\n    ...options,\n    enable: Boolean(csrfToken || oAuth2AccessToken),\n  };\n};\n\nconst useAppAsync = \u003c\n  U extends string,\n  T extends (...args: any[]) =\u003e Promise\u003cany\u003e\n\u003e(\n  key: U,\n  asyncFunction: T,\n  options?: UseAsyncOptions\u003cT\u003e\n) =\u003e {\n  // Enhance options using custom hooks\n  const optionsWithAuth = useAuthEnable(options ?? {});\n  const optionsWithErrorHandling = useErrorHandling(optionsWithAuth);\n\n  // Call the main useAsync hook with enhanced options\n  return useAsync(key, asyncFunction, optionsWithErrorHandling);\n};\n```\n\n## Why Choose `api-refetch` Over React Query or SWR?\n\nWhile React Query and SWR are excellent tools for data fetching and caching in React applications, `api-refetch` offers unique advantages that may make it more suitable for certain use cases:\n\n- **Zustand-based Storage**: `api-refetch` utilizes Zustand for state management, which avoids the need for a context provider or wrapper around your application, simplifying integration and reducing boilerplate.\n\n- **Preset data using Session Storage**: `api-refetch` provides a built-in mechanism for storing and retrieving data in session storage, allowing you to easily cache API responses and reuse them across your application. It can be use to accelerate the loading of our data before automatic revalidation.\n\n- **No Wrapper Store Provider Required**: Unlike other libraries that require you to wrap your application with a provider for state management, `api-refetch` operates without such requirements, making it easier to integrate with existing projects or for those seeking less complexity.\n\n- **Lightweight**: With a size of only 250 kB, `api-refetch` is significantly lighter than React Query (2.3 MB) and SWR (650 kB), making it an excellent choice for projects where payload size is a critical factor.\n\n- **Optimized for API Fetching**: This library is specifically optimized for API fetching scenarios within npm/react packages, providing just enough functionality to manage async operations effectively without over-engineering solutions.\n\n- **Easily Customizable and Extendable**: The codebase of `api-refetch` is designed to be easily understandable and modifiable. Developers can quickly copy the code into their applications and modify it according to their specific needs, providing a high degree of flexibility.\n\n- **Focused Functionality**: `api-refetch` focuses solely on the essentials of fetching, caching, and state management without bundling additional features that might not be necessary for all projects, thus keeping it streamlined and efficient.\n\nBy choosing `api-refetch`, developers can leverage a straightforward, highly customizable solution that integrates seamlessly with modern React applications, providing an efficient and effective alternative to more heavyweight options.\n\nThis section aims to clearly articulate the unique selling points of `api-refetch`, helping users to make an informed decision based on their specific requirements and the relative strengths of this library compared to other options in the market.\n\n## Understanding the Returned States\n\nWhen using the `useAsync` hook from `api-refetch`, it returns a variety of states and functions that help manage and respond to asynchronous operations seamlessly. Understanding these states is crucial for effectively handling data fetching, loading indicators, error handling, and more within your React components.\n\n### State Indicators\n\nHere’s a breakdown of each state returned by the `useAsync` hook:\n\n| **State**            | **Type**                                  | **Description**                                                                                                                                                                                               |\n| -------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `isFetched`          | `boolean`                                 | Indicates whether the data has been successfully fetched at least once. This is useful to determine if the initial data load has occurred.                                                                    |\n| `isLoading`          | `boolean`                                 | Represents whether the data is currently being fetched. It is `true` when a fetch operation is in progress, whether it's an initial fetch or a revalidation.                                                  |\n| `isInvalidated`      | `boolean`                                 | Signals whether the current data is considered invalid and needs to be refetched. This can be triggered manually or by other operations that invalidate the existing data.                                    |\n| `isSuccess`          | `boolean`                                 | Denotes that the data was fetched successfully without any errors. This state is `true` when the last fetch operation completed successfully.                                                                 |\n| `isDisabled`         | `boolean`                                 | Indicates whether the hook is disabled (`true`) or enabled (`false`). A disabled hook does not perform any fetching operations.                                                                               |\n| `isWaitingData`      | `boolean`                                 | As `isLoading`, `true` when the hook is loading data for the first time and there is no data yet. But it remains `true` as long data is available.                                                            |\n| `isRevalidating`     | `boolean`                                 | `true` when the hook is revalidating already fetched data in the background to ensure it is up to date. This helps in maintaining fresh data without disrupting the user experience.                          |\n| `error`              | `string \\| null`                          | Contains the error message if the fetch operation fails; otherwise, it is `null`. This is useful for displaying error messages to the user or triggering error-specific logic.                                |\n| `data`               | `any \\| null`                             | Holds the fetched data once the operation is successful; otherwise, it is `null`. This is the primary data used within your components.                                                                       |\n| `errorCount`         | `number`                                  | Tracks the number of consecutive errors that have occurred during fetch attempts. This is useful for implementing retry logic or displaying persistent error messages after multiple failures.                |\n| `revalidate`         | `(...args: any[]) =\u003e Promise\u003cany\u003e`        | A function to manually trigger a revalidation (refetch) of the data. This allows you to refresh the data on demand, such as when a user performs a pull-to-refresh action.                                    |\n| `setData`            | `(data: any \\| null) =\u003e void`             | A function to manually set or update the fetched data. This is useful for optimistic UI updates or when you need to modify the data without refetching it from the server.                                    |\n| `execute` as `[key]` | `[key]: (...args: any[]) =\u003e Promise\u003cany\u003e` | A dynamically named function based on the `key` parameter, allowing you to execute the fetch operation directly. For example, if the `key` is `'fetchUser'`, you can call `fetchUser()` to trigger the fetch. |\n\n## Contributing\n\nContributions are welcome! Please open an issue or submit a pull request with your suggestions or improvements.\n\n## License\n\n`api-refetch` is open-source software licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faymericzip%2Fapi-refetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faymericzip%2Fapi-refetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faymericzip%2Fapi-refetch/lists"}