{"id":15069941,"url":"https://github.com/idootop/xsta","last_synced_at":"2025-04-10T17:10:56.399Z","repository":{"id":206792703,"uuid":"717673236","full_name":"idootop/xsta","owner":"idootop","description":"⚡ An ultra-lightweight (\u003c200 lines) React state management solution with zero learning curve and migration costs.","archived":false,"fork":false,"pushed_at":"2024-05-18T04:41:04.000Z","size":259,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-23T16:04:16.452Z","etag":null,"topics":["react-state-management","tiny","typscript","zustand"],"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/idootop.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":"2023-11-12T07:38:47.000Z","updated_at":"2025-03-14T06:03:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"4affba8b-3d11-4524-adb3-6193c87deac2","html_url":"https://github.com/idootop/xsta","commit_stats":null,"previous_names":["idootop/xsta"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idootop%2Fxsta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idootop%2Fxsta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idootop%2Fxsta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idootop%2Fxsta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idootop","download_url":"https://codeload.github.com/idootop/xsta/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246981161,"owners_count":20863828,"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":["react-state-management","tiny","typscript","zustand"],"created_at":"2024-09-25T01:45:40.954Z","updated_at":"2025-04-10T17:10:56.380Z","avatar_url":"https://github.com/idootop.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n![XSta Logo](/assets/cover.webp)\n\n\u003cdiv align=\"center\"\u003e\u003cstrong\u003e⚡️ An ultra-lightweight React state management solution\u003c/strong\u003e\u003c/div\u003e\n\u003cdiv align=\"center\"\u003eLess than 200 lines of code, with zero learning curve and migration costs\u003c/div\u003e\n\u003cbr/\u003e\n\n[![中文文档](https://img.shields.io/badge/-中文文档-blue)](https://github.com/idootop/xsta/blob/main/README.zh-CN.md) [![NPM Version](https://badgen.net/npm/v/xsta)](https://www.npmjs.com/package/xsta) [![Minizipped Size](https://img.shields.io/bundlephobia/minzip/xsta)](https://www.npmjs.com/package/xsta) [![Downloads](https://img.shields.io/npm/dm/xsta.svg)](https://www.npmjs.com/package/xsta) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fidootop%2Fxsta.svg?type=shield\u0026issueType=license)](https://github.com/idootop/xsta)\n\n\u003c/div\u003e\n\n`XSta` is an ultra-lightweight (\u003c200 lines) React state management solution that provides an intuitive `useState` Hook-like interface, offering a seamless state management experience with zero learning curve and migration cost.\n\n## ✨ Highlights\n\n- **🐦 Tiny yet Powerful** Less than 200 lines of code, a full-fledged React state management solution, battle-tested for production.\n- **🧩 Zero Learning and Migration Costs** Just replace `useState` with `useXState`, and the local component state becomes instantly shareable across other components - it's that easy!\n- **💪 Performance Optimized** Only re-render when component's subscribed state changes, effortlessly optimizing complex page performance.\n\n## 📦 Installation\n\n```bash\n# With npm\nnpm install xsta\n\n# With pnpm\npnpm install xsta\n\n# With Yarn\nyarn add xsta\n```\n\n## ⚡️ Get Started\n\nSimply replace `useState` with `useXState` and provide a unique `key` to turn your local component state into a globally shareable state.\n\n\u003cdetails open\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\nimport { useXState } from 'xsta';\n\nexport default function Counter() {\n  const [count, setCount] = useXState('count', 0); //  It's that easy!\n\n  function handleClick() {\n    setCount(count + 1);\n  }\n\n  return (\n    \u003cbutton onClick={handleClick}\u003e\n      \u003cp\u003eYou pressed me {count} times\u003c/p\u003e\n    \u003c/button\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\nYou can also directly access and modify specific state from anywhere outside components using `XSta`.\n\nWhen the external state changes, dependent components will automatically update.\n\n\u003cdetails open\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\nimport { useXState, XSta } from 'xsta';\n\nfunction externalFunction() {\n  const count = XSta.get('count');\n  XSta.set('count', count + 1);\n}\n\nexport default function Counter() {\n  const [count, setCount] = useXState('count', 0);\n\n  return (\n    \u003cbutton onClick={externalFunction}\u003e\n      \u003cp\u003eYou pressed me {count} times\u003c/p\u003e\n    \u003c/button\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\n## 💎 Best Practices\n\nTo better manage state during development, it's common to encapsulate state-related operations by module.\n\n`XStaManager` provides a basic state management interface for this purpose. Here's a simple example of `createXStaManager`.\n\n\u003cdetails\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\n// counter.state.ts\nimport { createXStaManager } from 'xsta';\n\nexport const CounterState = createXStaManager({\n  key: 'count',\n  initialState: 0,\n});\n\n// Counter.ts\nimport { CounterState } from 'counter.state';\n\nfunction externalFunction() {\n  CounterState.setState(count =\u003e count + 1);\n}\n\nexport default function Counter() {\n  const [count] = CounterState.useState();\n\n  return (\n    \u003cbutton onClick={externalFunction}\u003e\n      \u003cp\u003eYou pressed me {count} times\u003c/p\u003e\n    \u003c/button\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\nFurthermore, you can extend `XStaManager` and provide a unified state management interface. **(Recommended)**\n\n\u003cdetails open\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\n// counter.state.ts\nimport { XStaManager } from 'xsta';\n\nclass _CounterState extends XStaManager\u003cnumber\u003e {\n  key = 'count';\n  initialState = 0;\n\n  get oddOrEven() {\n    return this.getState() \u0026 1 ? 'odd' : 'even';\n  }\n\n  increase = () =\u003e {\n    this.setState(count =\u003e count + 1);\n  };\n\n  decrease = () =\u003e {\n    this.setState(count =\u003e count - 1);\n  };\n}\n\nexport const CounterState = new _CounterState();\n\n// Counter.ts\nimport { CounterState } from 'counter.state';\n\nexport default function Counter() {\n  const [count] = CounterState.useState();\n\n  return (\n    \u003c\u003e\n      \u003cp\u003eYou pressed me {count} times\u003c/p\u003e\n      \u003cp\u003eCount is {CounterState.oddOrEven}\u003c/p\u003e\n      \u003cbutton onClick={CounterState.increase}\u003eIncrease\u003c/button\u003e\n      \u003cbutton onClick={CounterState.decrease}\u003eDecrease\u003c/button\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\n## ⚙️ Advanced\n\n### XConsumer\n\nIf a component is computationally expensive to build, or if your state is a complex object with multiple components depending on different properties, you can wrap it with `XConsumer` and use a state selector to control when the child components should re-render.\n\n\u003cdetails\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\nimport { useXState, XConsumer } from 'xsta';\n\nexport default function UserProfile() {\n  const [profile, setProfile] = useXState('profile', {\n    avatar: 'https://github.com/fluidicon.png',\n    age: 18,\n    bio: 'hello world!',\n  });\n\n  console.log('UserProfile rebuild', profile);\n\n  return (\n    \u003c\u003e\n      \u003cXConsumer provider=\"profile\" selector={s =\u003e s.avatar}\u003e\n        \u003cUserAvatar /\u003e {/* UserAvatar will only re-render when avatar changes */}\n      \u003c/XConsumer\u003e\n      \u003cXConsumer provider=\"profile\" selector={s =\u003e [s.age, s.bio]}\u003e\n        {profile =\u003e {\n          // You can also directly access the current state value\n          return \u003cUserInfo age={profile.age} bio={profile.bio} /\u003e;\n        }}\n      \u003c/XConsumer\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\n### useConsumer\n\n`useXConsumer` is an alias for `useXState` that allows for more convenient subscription to state updates.\n\n\u003cdetails\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\nimport { useXConsumer } from 'xsta';\n\nfunction WatchText() {\n  // This component will automatically re-render when myState.text changes\n  const [state] = useXConsumer('myState', s =\u003e s.text);\n  return \u003cp\u003eCurrent text: {state.text}\u003c/p\u003e;\n}\n```\n\n\u003c/details\u003e\n\n### Additional Features\n\n`XSta` provides a few more utilities for advanced use cases:\n\n- `useXProvider(key, initialState)`: Initializes a global state value.\n- `XSta.delete(key)`: Deletes a global state value.\n- `XSta.clear(key)`: Clears all global state values.\n\n\u003cdetails\u003e\n\u003csummary\u003e👉 Example\u003c/summary\u003e\n\n```typescript\nimport { useXState, useXProvider, XSta } from 'xsta';\n\nconst initialState = 0;\n\nexport default function APP() {\n  // Initialize state\n  useXProvider('count', initialState);\n\n  return (\n    \u003c\u003e\n      \u003cCountViewer /\u003e\n      \u003cIncrease /\u003e\n      \u003cClear /\u003e\n    \u003c/\u003e\n  );\n}\n\nfunction Clear() {\n  return (\n    \u003cbutton\n      onClick={() =\u003e {\n        // Delete the \"count\" state\n        XSta.delete('count');\n        // Clear all states\n        XSta.clear();\n      }}\n    \u003e\n      Clear\n    \u003c/button\u003e\n  );\n}\n\nfunction CountViewer() {\n  const [count] = useXState('count');\n\n  return \u003cp\u003eYou pressed me {count ?? initialState} times\u003c/p\u003e;\n}\n\nfunction Increase() {\n  return (\n    \u003cbutton\n      onClick={() =\u003e {\n        XSta.set('count', XSta.get('count', initialState) + 1);\n      }}\n    \u003e\n      Increase\n    \u003c/button\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\nNote: By default, `XSta` does not automatically initialize or clean up global states. Instead, developers decide when to initialize and destroy state values. Therefore, please be careful when using it to prevent issues like using an uninitialized state or memory leaks.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidootop%2Fxsta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidootop%2Fxsta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidootop%2Fxsta/lists"}