{"id":15162301,"url":"https://github.com/z0al/oktane","last_synced_at":"2025-09-30T15:31:51.416Z","repository":{"id":57314046,"uuid":"216785881","full_name":"z0al/oktane","owner":"z0al","description":"⚛️  A light-weight and customizable library for data fetching in React","archived":true,"fork":false,"pushed_at":"2020-05-03T21:17:19.000Z","size":1478,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-24T02:49:31.745Z","etag":null,"topics":["cache","data-driven","fetch","graphql","hooks","mutation","query","react","react-query","rest-api","stream","subscription"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/z0al.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-22T10:25:25.000Z","updated_at":"2023-01-28T11:03:49.000Z","dependencies_parsed_at":"2022-09-13T02:31:45.113Z","dependency_job_id":null,"html_url":"https://github.com/z0al/oktane","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/z0al/oktane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z0al%2Foktane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z0al%2Foktane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z0al%2Foktane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z0al%2Foktane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/z0al","download_url":"https://codeload.github.com/z0al/oktane/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z0al%2Foktane/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277712655,"owners_count":25864405,"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","status":"online","status_checked_at":"2025-09-30T02:00:09.208Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cache","data-driven","fetch","graphql","hooks","mutation","query","react","react-query","rest-api","stream","subscription"],"created_at":"2024-09-27T01:22:43.812Z","updated_at":"2025-09-30T15:31:51.145Z","avatar_url":"https://github.com/z0al.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Oktane\n\n[![npm package](https://badgen.net/npm/v/oktane)][npm]\n[![npm bundle size](https://badgen.net/bundlephobia/minzip/oktane@latest)][bundlephobia]\n\n\u003e **Current status:** 🚧 In alpha stage so expect breaking changes. Check out the [roadmap](https://github.com/z0al/oktane/issues/3) for more info.\n\nA light-weight and customizable library for data fetching in React.\n\n## Features\n\n- 📦 Minimal footprint (\u003c 3kb gzipped)\n- 🌐 Backend agnostic\n- 🧹 Automatic Garbage collection\n- 🔫 Request cancellation\n- ⏫ Parallel / Dependent Queries\n- 🔃 Subscriptions / Lazy queries\n- 🔌 Plugins support\n- 💙 TypeScript ready\n- [and more ...](./examples)\n\n## Installation\n\n\u003e Requires React v16.8.6 or higher\n\n```sh\nnpm add oktane\n```\n\n## Basic usage\n\n[![Open in CodeSandbox][csb]][basic-demo]\n\n### Creating the client\n\n```javascript\nimport { createClient, ClientProvider } from 'oktane';\n\nconst client = createClient({\n  fetch: ({ query }) =\u003e {\n    return fetch(\n      `https://jsonplaceholder.typicode.com/${query}`\n    ).then((res) =\u003e res.json());\n  },\n});\n\nconst App = () =\u003e (\n  \u003cClientProvider value={client}\u003e\n    \u003cTodos /\u003e\n  \u003c/ClientProvider\u003e\n);\n```\n\n### Fetching data\n\n```javascript\nimport { useQuery } from 'oktane';\n\nconst Todos = () =\u003e {\n  const { data, status } = useQuery('todos');\n\n  if (status === 'pending') {\n    return \u003cp\u003eloading ...\u003c/p\u003e;\n  }\n\n  return (\n    \u003c\u003e\n      \u003ch2\u003eTodo list\u003c/h2\u003e\n      \u003cul\u003e\n        {data.map((todo) =\u003e (\n          \u003cli key={todo.id}\u003e{todo.title}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n## How it works\n\nMany data fetching libraries provide multiple React hooks to support use cases e.g. `useSubscription`, `useInfiniteQuery` ..etc. To minimize the API surface Oktane takes a different approach.\n\nHere how someone would make a request using the [useQuery](#usequery) hook provided by Oktane:\n\n```javascript\nconst { data, error, hasMore, fetchMore, ...rest } = useQuery(/* query */);\n```\n\n\u003e **Note:** [useManualQuery](#useManualQuery) hook works the same way as `useQuery` except it doesn't fetch the request automatically on mount/updates but rather exposes a helper to manually fetch when needed.\n\nWhen resolving a request, Oktane checks the value returned by `clientOptions.fetch(request, ctx)` call and does one of the following based to the type:\n\n- **Promise:** ([demo][basic-demo] )\n  - Waits for the Promise to resolve and then set `data` to the result.\n  - In the case of error, Oktane will catch the error and expose it as `error`.\n  - Calling `hasMore` will always return false.\n  - **Use case:** API Calls, loading data from LocalStorage ...etc.\n- **Iterable / Async Iterable:**  ([demo][infinite-demo] )\n  - Calls `iterator.next()` **once** and sets `data` to the result.\n  - Next values can be emitted by calling `fetchMore`.\n  - Calling `hasMore` will return true as long as the iterator doesn't complete.\n  - In the case of error, Oktane will catch the error and expose it as `error`.\n  - **Use case:** Infinite scroll.\n- **Callback function:**  ([demo][subscription-demo] )\n  - Assumes a function that accepts a subscriber and optionally returns a function to close subscription (i.e. unsubscribe).\n  - Any value passed to `subscriber.next()` will be available as `data`.\n  - Calling `subscriber.error()` will set the value to `error` and close the subscription.\n  - Calling `subscriber.complete()` will mark the request as completed and close the subscription.\n  - Calling `hasMore` will always return false.\n  - **Use case:** Anything you would use an Observable for e.g. Web Socket.\n- **Anything else:** wraps it in `Promise.resolve` and applies the Promise rule above.\n\nIt's worth mentioning that custom plugins may alter the behavior described above. For example, a plugin may decide not to report errors back to the React hook and instead retry the request every time it fails.\n\n### API\n\n#### createClient\n\n```javascript\nfunction createClient(options: ClientOptions): Client\n```\n\n**Arguments**\n\n- **options (object)**\n  - **fetch (function):** The function that resolves all requests. **Required**.\n  - **plugins (array):** An array of custom plugins.\n  - **cache (object)**\n    - **disposeTime (number):** A timeout for unused requests. Default is 30 seconds.\n\n#### useQuery\n\n```javascript\nfunction useQuery(query: QueryFunc  | any): {\n  cancel: () =\u003e void;\n  refetch: () =\u003e void;\n  hasMore: () =\u003e boolean;\n  fetchMore: () =\u003e void;\n}\n```\n\n#### useManualQuery\n\n```javascript\nfunction useManualQuery(query: any): {\n  fetch: () =\u003e void;\n  cancel: () =\u003e void;\n  refetch: () =\u003e void;\n  hasMore: () =\u003e boolean;\n  fetchMore: () =\u003e void;\n}\n```\n\n## Examples\n\nCheck out the [examples](./examples) folder.\n\n## Credits\n\nInspired by the following great libraries:\n\n- [Redux][redux]: Predictable state container for JavaScript apps.\n- [SWR][swr]: React Hooks library for remote data fetching.\n- [React Query][react-query]: Hooks for fetching, caching, and updating asynchronous data in React.\n\n## License\n\nMIT © Ahmed T. Ali\n\n[npm]: https://npm.im/oktane\n[bundlephobia]: https://bundlephobia.com/result?p=oktane@latest\n[redux]: https://github.com/reduxjs/redux\n[swr]: https://github.com/zeit/swr\n[react-query]: https://github.com/tannerlinsley/react-query/\n[csb]: https://img.shields.io/badge/Open%20in-CodeSandbox-blue?style=flat-square\u0026logo=codesandbox\n[basic-demo]: https://codesandbox.io/s/github/z0al/oktane/tree/master/examples/basic\n[infinite-demo]: https://codesandbox.io/s/github/z0al/oktane/tree/master/examples/infinite\n[subscription-demo]: https://codesandbox.io/s/github/z0al/oktane/tree/master/examples/subscription\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz0al%2Foktane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fz0al%2Foktane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz0al%2Foktane/lists"}