{"id":15386436,"url":"https://github.com/h-a-n-a/stateliss","last_synced_at":"2025-04-15T20:09:04.312Z","repository":{"id":112749967,"uuid":"283106893","full_name":"h-a-n-a/stateliss","owner":"h-a-n-a","description":"😈 Light weight library with hook support for state/async state management of React","archived":false,"fork":false,"pushed_at":"2021-07-08T15:51:16.000Z","size":172,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T20:08:57.297Z","etag":null,"topics":["async","custom-hook","hook","provider","react","state-management"],"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/h-a-n-a.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2020-07-28T05:14:34.000Z","updated_at":"2021-07-08T15:51:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"d06917da-7fd6-4387-8b17-7b2885eec633","html_url":"https://github.com/h-a-n-a/stateliss","commit_stats":{"total_commits":27,"total_committers":1,"mean_commits":27.0,"dds":0.0,"last_synced_commit":"6c27932e6c7d339df079659aba8d3a4b81cdf3fd"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-a-n-a%2Fstateliss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-a-n-a%2Fstateliss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-a-n-a%2Fstateliss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-a-n-a%2Fstateliss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/h-a-n-a","download_url":"https://codeload.github.com/h-a-n-a/stateliss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249145302,"owners_count":21219966,"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":["async","custom-hook","hook","provider","react","state-management"],"created_at":"2024-10-01T14:49:22.239Z","updated_at":"2025-04-15T20:09:04.292Z","avatar_url":"https://github.com/h-a-n-a.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stateliess\n\n\u003e React Hook 状态管理于无形\n\n## 特性\n\n- 支持异步状态处理\n- 底层使用 `Context.Provider` 实现，支持 Custom Hook 完整生命周期\n- API 简单易懂，极速上手\n- TypeScript 支持\n\n## 在线体验\n\n[![Edit](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/unshaped-demo-b2tw5)\n\n## 安装\n\n```bash\nnpm install stateliss --save\n```\n\n## 简易上手\n\n### 创建一个 Store\n\n使用 `createStore` 包装一个 custom hook，将其转化为状态持久化的容器\n\n```tsx\nimport { useState } from 'react'\nimport { createStore } from 'stateliss'\n\nfunction useCounter() {\n  const [count, setCount] = useState(0)\n  const increment = () =\u003e setCount(count + 1)\n  const decrement = () =\u003e setCount(count - 1)\n  return { count, increment, decrement }\n}\n\nexport default createStore(useCounter)\n```\n\n### 使用一个 Store\n\n使用 `useStore` 包裹刚刚创建完成的 Store 即可获取经过持久化的数据。不要忘记包裹 `Provider`！\n\n```tsx\nimport React from 'react'\nimport { useStore } from 'stateliss'\n\nimport CounterStore from './CounterStore'\n\nfunction Counter() {\n  const { count, increment, decrement } = useStore(CounterStore)\n  return (\n    \u003c\u003e\n      \u003cdiv\u003eCount: {count}\u003c/div\u003e\n      \u003cbutton onClick={increment}\u003e+1\u003c/button\u003e\n      \u003cbutton onClick={decrement}\u003e-1\u003c/button\u003e\n    \u003c/\u003e\n  )\n}\n\nfunction App() {\n  return (\n    \u003cCounterStore.Provider\u003e\n      \u003cCounter /\u003e\n    \u003c/CounterStore.Provider\u003e\n  )\n}\n\nexport default App\n```\n\n## 进阶使用\n\n### 参数传递\n\n有的时候我们希望 custom hook 能接受一个参数，你可以在这里写成一个对象，如下方 `useCounter` 所示\n\n```tsx\nimport React, { useState } from 'react'\nimport { createStore } from 'stateliss'\n\nfunction useCounter({ defaultValue }: { defaultValue: number }) {\n  const [count, setCount] = useState(defaultValue)\n  const increment = () =\u003e setCount(count + 1)\n  const decrement = () =\u003e setCount(count - 1)\n  return { count, increment, decrement }\n}\n\nexport default createStore(useCounter)\n```\n\n然后在 `Provider` 上提供这个参数：\n\n```tsx\nfunction App() {\n  return (\n    \u003cCounterStore.Provider defaultValue={10}\u003e\n      \u003cCounter /\u003e\n    \u003c/CounterStore.Provider\u003e\n  )\n}\n\nexport default App\n```\n\n### 异步请求\n\n除了我们能在普通的自定义 Hook 中进行异步请求，`stateliss` 还提供了相应的请求处理 API：\n\n```typescript\n// api.ts\nexport function getEmail({ userId }: { userId: string }): Promise\u003cnumber\u003e {\n  return fetch(`url-to-fetch-email/${userId}`).then((res) =\u003e res.text())\n}\n```\n\n```tsx\nimport React from 'react'\nimport { createAsyncStore, useAsyncStore } from 'stateliss'\nimport { getEmail } from './api'\n\nconst UserStore = createAsyncStore({\n  getEmail\n})\n\nconst UserInfo = () =\u003e {\n  const { getEmail } = useAsyncStore(UserStore)\n  return (\n    \u003c\u003e\n      \u003cdiv\u003eEmail: {getEmail.loading ? 'Loading Email...' : getEmail.data}\u003c/div\u003e\n      \u003cbutton onClick={() =\u003e getEmail.run({ userId: 'some-user-id' })}\u003e\n        fetch Email\n      \u003c/button\u003e\n    \u003c/\u003e\n  )\n}\n\nconst App = () =\u003e {\n  return (\n    \u003cUserStore.Provider getEmail={{ userId: 'default-user-id' }}\u003e\n      \u003cUserInfo /\u003e\n    \u003c/UserStore.Provider\u003e\n  )\n}\n\nexport default App\n```\n\n## API\n\n### `createStore`\n\n传入一个 custom hook 并创建一个 Store ，但你无需关心他返回了什么，`useStore` 会帮你处理一切\n\n```ts\nconst Store = createStore\u003cT, U\u003e(\n  hook: (props: T) =\u003e U\n)\n```\n\n### `useStore`\n\n使用一个 Store ，并返回自定义 hook 的返回结果。\n\n注：该组件需要被 `Provider` 包裹\n\n```ts\nconst state: StoreValueType\u003cT\u003e = useStore\u003cT extends Store\u003cany, any\u003e\u003e(\n  store: T,\n  depFn?: Deps\u003cStoreValueType\u003cT\u003e\u003e\n)\n```\n\n### `createAsyncStore`\n\n传入一个 `AsyncFunction`（或 key 为 AsyncFunction 的 id，value 为 `AsyncFunction` 的对象，即`Record\u003cstring, AsyncFn\u003cany, any\u003e\u003e`）\n并返回一个 Async Store，用于跟踪异步状态和持久化 `Promise` 的返回结果。\n\n```ts\nconst AsyncStore: Store\u003c\n  AsyncFnPropsType\u003cT\u003e,\n  AsyncData\u003cAsyncFnPropsType\u003cT\u003e, AsyncFnDataType\u003cT\u003e\u003e\n\u003e = createAsyncStore\u003cT extends AsyncFn\u003cany, any\u003e\u003e(\n  asyncFn: T\n)\nconst AsyncStore: ComposedStore\u003cPartial\u003cComposedAsyncFnPropsType\u003cT\u003e\u003e, ComposedContextType\u003cT\u003e\u003e\n = createAsyncStore\u003cT extends Record\u003cstring, AsyncFn\u003cany, any\u003e\u003e\u003e(\n  asyncFn: T\n)\n```\n\n### `useAsyncStore`\n\n和 `useStore` 不同的是，它可以跟踪异步信息，如下所示：\n\n```ts\nconst {\n  data,\n  loading,\n  error,\n  refresh,\n  run\n} =  useAsyncStore\u003cT extends Store\u003cany, any\u003e\u003e(\n  store: T,\n  options?: {\n    depFn?: Deps\u003cStoreValueType\u003cT\u003e\u003e\n  }\n)\n\nconst {\n  asyncFn1: { data, loading, error, refresh, run },\n  asyncFn2: { data, loading, error, refresh, run }\n} = useAsyncStore\u003cT extends ComposedStore\u003cany, any\u003e\u003e(\n  store: T,\n  options?: {\n    depFn?: Deps\u003cComposedKeyValueType\u003cT\u003e\u003e\n  }\n)\n```\n\n#### 参数说明\n\n| 参数          | 类型                                                                                     | 描述                                                |\n| ------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------- |\n| store         | \u003ccode\u003eStore \u0026#124; ComposedStore \u003c/code\u003e                                                 | `createAsyncStore` 返回的 Store                     |\n| options.depFn | \u003ccode\u003e(store: Deps\u003cStoreValueType\u003cT\u003e \u0026#124; ComposedKeyValueType\u003cT\u003e\u003e) =\u003e unkown[]\u003c/code\u003e | 当 `depFn` 的返回值发生改变才进行渲染，用于性能优化 |\n\n#### 返回值\n\n| 参数    | 类型                | 描述                                                      |\n| ------- | ------------------- | --------------------------------------------------------- |\n| data    | `StoreValueType\u003cT\u003e` | `Async Function` 返回的数据                               |\n| error   | `any`               | `Async Function` 捕获到的错误信息                         |\n| loading | `boolean`           | `Async Function` 的 `loading` 状态                        |\n| run     | `(param?) =\u003e void`  | 发起请求，如果没有 `param` 则默认为传入 `Provider` 的参数 |\n| refresh | `() =\u003e void`        | 使用上一次的参数重新发起请求                              |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-a-n-a%2Fstateliss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fh-a-n-a%2Fstateliss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-a-n-a%2Fstateliss/lists"}