{"id":28384284,"url":"https://github.com/aardio/statecontroller","last_synced_at":"2025-06-25T23:31:13.594Z","repository":{"id":57369880,"uuid":"207105628","full_name":"aardio/stateController","owner":"aardio","description":"State Management with React Hooks","archived":false,"fork":false,"pushed_at":"2022-10-31T04:07:46.000Z","size":32,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-22T08:03:10.309Z","etag":null,"topics":["hooks","management","react","react-hooks","react-state","react-state-management","reactjs","state","state-management","typescript"],"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/aardio.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-09-08T11:57:04.000Z","updated_at":"2023-03-09T07:13:28.000Z","dependencies_parsed_at":"2022-09-10T15:31:39.539Z","dependency_job_id":null,"html_url":"https://github.com/aardio/stateController","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aardio/stateController","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aardio%2FstateController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aardio%2FstateController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aardio%2FstateController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aardio%2FstateController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aardio","download_url":"https://codeload.github.com/aardio/stateController/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aardio%2FstateController/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261972588,"owners_count":23238537,"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":["hooks","management","react","react-hooks","react-state","react-state-management","reactjs","state","state-management","typescript"],"created_at":"2025-05-30T08:10:07.402Z","updated_at":"2025-06-25T23:31:13.539Z","avatar_url":"https://github.com/aardio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# State Controller\n\n\u003ca href=\"https://npmjs.org/package/state-controller\"\u003e\u003cimg alt=\"NPM version\" src=\"https://img.shields.io/npm/v/state-controller.svg?style=flat-square\"\u003e\u003c/a\u003e\n\u003ca href=\"https://npmjs.org/package/state-controller\"\u003e\u003cimg alt=\"NPM downloads\" src=\"https://img.shields.io/npm/dm/state-controller.svg?style=flat-square\"\u003e\u003c/a\u003e\n\u003ca href=\"https://unpkg.com/state-controller\"\u003e\u003cimg alt=\"Size\" src=\"https://img.badgesize.io/https://unpkg.com/state-controller?style=flat-square\"\u003e\u003c/a\u003e\n\nState management with React Hooks\n\n## Installation\n\n```sh\nnpm i state-controller\nyarn add state-controller\n```\n\n## Example \n\n[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/floral-browser-lpimg)\n\n![Screenshot](https://raw.githubusercontent.com/aardio/stateController/master/screenshots/screenshot.gif)\n\n###   store/useCounterController.ts\n\n```js\nimport { useState } from \"react\"\nimport stateController,{useIfMounted} from \"state-controller\" \nimport useUserController from \"./useUserController\"\n \nlet useValue = ({n=0}) =\u003e {\n\n    const [counter, setCounter] = useState({value: n })\n    const [,userController] = useUserController()\n    const [ifMounted,loading] = useIfMounted();\n\n    const controller = {\n        \n        increment(n: number){\n            setCounter({ ...counter, value: counter.value + n })\n            userController.setLastActiveTime( new Date() )\n        },\n\n        update(){\n\n            ifMounted(\n              async ()=\u003e{\n                  return {value:2}\n              }\n            ).then( setCounter ).catch( e =\u003e e \u0026\u0026 console.error(e) )\n\n\n            ifMounted({value:2}).then( setCounter )\n\n            if( ifMounted() ){\n              setCounter({value:2})\n            }\n        }\n    }\n \n    return [counter,controller,loading] as const;\n}\n\nlet useCounterController = stateController.create(useValue)\nexport default useCounterController\n```\n\n###   store/useUserController.ts\n\n```js\nimport { useState, useMemo } from \"react\"\nimport stateController from \"state-controller\" \n \nconst useValue = () =\u003e {\n \n    const [user, setUser] = useState({\n        name: \"\", \n        lastActiveTime: new Date()\n    }) \n \n    const controller = useMemo( ()=\u003e({ \n        setName(n: string){\n            setUser( user=\u003e({ ...user, name: n }) )\n        }, \n        setLastActiveTime(d:Date){\n            setUser( user=\u003e( { ...user,  lastActiveTime: d} ) )\n        },\n    }),[])\n\n    return [user,controller] as const;\n}\n\nlet useUserController = stateController.create(useValue)\nexport default useUserController\n```\n\n###  \"Counter.tsx\"\n\n```js\n\nimport React, { useEffect } from \"react\"\nimport useCounterController from \"./store/useCounterController\"\nimport useUserController from \"./store/useUserController\"\n\nconst Counter:React.FC\u003c{}\u003e = () =\u003e  {\n \n  const [counter,counterController] = useCounterController()\n  const [user,userController] = useUserController()\n\n  useEffect(\n     ()=\u003e{\n        userController.setName(\"stateController\")\n     },[userController]\n  )\n  \n  return (\n    \u003cdiv\u003e\n      name: { user.name }\u003cbr /\u003e \n      value: {counter.value}\u003cbr /\u003e \n      \u003cbutton onClick={ () =\u003e { \n        counterController.increment(1);  \n      } }\u003eadd\u003c/button\u003e  { user.lastActiveTime.toLocaleString() }\n      \u003cbr /\u003e \u003cbr /\u003e \n    \u003c/div\u003e\n  )\n}\n \nexport default Counter;\n```\n### index.tsx\n\n```js\nimport React from \"react\"\nimport ReactDOM from 'react-dom'; \nimport Counter from \"./Counter\"\nimport useUserController from \"./store/useUserController\";\nimport useCounterController from \"./store/useCounterController\";\nimport stateController from \"state-controller\" \n\nconst App: React.FC = () =\u003e {  \n    \n  let  useStore = stateController.combine(useUserController,useCounterController)\n  return ( \n      \u003cuseStore.Provider \u003e \n        \u003cCounter /\u003e\n        \u003cCounter /\u003e\n      \u003c/useStore.Provider\u003e  \n  );\n}\n \nReactDOM.render(\u003cApp /\u003e, document.getElementById('root'));\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faardio%2Fstatecontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faardio%2Fstatecontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faardio%2Fstatecontroller/lists"}