{"id":13450504,"url":"https://github.com/mcclayton/react-state-patterns","last_synced_at":"2025-03-23T16:31:32.489Z","repository":{"id":34295006,"uuid":"175096388","full_name":"mcclayton/react-state-patterns","owner":"mcclayton","description":"Tiny utility package for easily creating reusable implementations of React state provider patterns.","archived":false,"fork":false,"pushed_at":"2023-01-07T03:56:56.000Z","size":2476,"stargazers_count":16,"open_issues_count":18,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-09-24T17:37:32.438Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/mcclayton.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-03-11T22:55:37.000Z","updated_at":"2022-11-08T20:57:27.000Z","dependencies_parsed_at":"2023-01-15T06:15:37.905Z","dependency_job_id":null,"html_url":"https://github.com/mcclayton/react-state-patterns","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcclayton%2Freact-state-patterns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcclayton%2Freact-state-patterns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcclayton%2Freact-state-patterns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcclayton%2Freact-state-patterns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcclayton","download_url":"https://codeload.github.com/mcclayton/react-state-patterns/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221856412,"owners_count":16892438,"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":[],"created_at":"2024-07-31T07:00:35.366Z","updated_at":"2024-10-28T16:31:20.956Z","avatar_url":"https://github.com/mcclayton.png","language":"JavaScript","funding_links":[],"categories":["Packages","JavaScript"],"sub_categories":[],"readme":"![Logo](https://github.com/mcclayton/react-state-patterns/blob/master/assets/logo.png)\n\n# react-state-patterns\n[![npm version](https://badge.fury.io/js/react-state-patterns.svg)](https://badge.fury.io/js/react-state-patterns)\n[![License](https://img.shields.io/npm/l/react-state-patterns.svg)](https://github.com/mcclayton/react-state-patterns/blob/master/LICENSE)\n[![CircleCI](https://circleci.com/gh/mcclayton/react-state-patterns.svg?style=svg)](https://circleci.com/gh/mcclayton/react-state-patterns)\n\nTiny utility package for easily creating reusable implementations of React state provider patterns.\n\n🚀  [react-state-patterns](https://www.npmjs.com/package/react-state-patterns) makes it easy to (and reduces boilerplate) create implementations of common React state provider patterns.\n\n⚠️  Powered by React Hooks under the hood. (This library has a peer dependency on `react: \u003e= 16.8.0`)\n\n#### Why?\n`react-state-patterns` is incredibly simple, small, and lightweight — making it a great choice for applications that wish to keep their footprint small and do not want a complex state management solution.\nThis library is also great for those that wish to utilize React Hooks for reusable state but do not want to couple their presentational components directly with state (this makes unit testing components *much* easier 🌟).\n\n`react-state-patterns` also makes state management modular — increasing code clarity and making organization of state a breeze 🍃.\n\n# Getting Started\n\n## Install\n```bash\nnpm install react-state-patterns --save\n```\n\n## Creating State Patterns\n\n#### Directly From Hook\n```jsx\nimport useProviders, { hookSchema } from 'react-state-patterns';\n\n// Create the state provider patterns\nconst Counter = useProviders(props =\u003e {\n  const [count, setCount] = useState(props.initialValue || 0);\n  const handlers = {\n    incrementBy: value =\u003e setCount(count + value),\n    decrementBy: value =\u003e setCount(count - value)\n  };\n  // hookSchema(...)\n  //    =\u003e { counter: { state: { count: 0 }, handlers: { incrementBy: (v) =\u003e {...}, decrementBy: (v) =\u003e {...} } } }\n  return hookSchema({ count: count }, handlers, \"counter\");\n});\n\n// Counter = { useHook, withState, State, Provider, Consumer }\n```\n\n#### Using `useStateHook` util\n[useStateHook API Docs](https://github.com/mcclayton/react-state-patterns/blob/master/API.md#useStateHook)\n```jsx\nimport useProviders, { useStateHook } from 'react-state-patterns';\n\n// Create the state patterns\nconst Counter = useProviders(\n  useStateHook(\n    (props) =\u003e ({ count: props.initialValue || 0 }),\n    {\n      incrementBy: state =\u003e value =\u003e ({ ...state, count: state.count + value }),\n      decrementBy: state =\u003e value =\u003e ({ ...state, count: state.count - value })\n    },\n    \"counter\"\n  )\n);\n\n// Counter = { useHook, withState, State, Provider, Consumer }\n```\n\n## Use the patterns\n\n#### Decorator Pattern\n```jsx\nconst Displayer = ({ counter: { state, handlers }}) =\u003e (\n  \u003cReact.Fragment\u003e\n    \u003cdiv\u003e{state.count}\u003c/div\u003e\n    \u003cbutton onClick={() =\u003e handlers.decrementBy(1)}\u003eDecrement\u003c/button\u003e\n    \u003cbutton onClick={() =\u003e handlers.incrementBy(1)}\u003eIncrement\u003c/button\u003e\n  \u003c/React.Fragment\u003e\n);\n\nconst StatefulDisplayer = Counter.withState(Displayer);\n\nconst rootElement = document.getElementById(\"root\");\nReactDOM.render(\u003cStatefulDisplayer initialValue={5} /\u003e, rootElement);\n```\n\n#### Render Prop Pattern\n```jsx\nconst Displayer = (props) =\u003e (\n  \u003cCounter.State initialValue={5}\u003e\n    {({ counter: { state, handlers } }) =\u003e (\n      \u003cReact.Fragment\u003e\n        \u003cdiv\u003e{state.count}\u003c/div\u003e\n        \u003cbutton onClick={() =\u003e handlers.decrementBy(1)}\u003eDecrement\u003c/button\u003e\n        \u003cbutton onClick={() =\u003e handlers.incrementBy(1)}\u003eIncrement\u003c/button\u003e\n      \u003c/React.Fragment\u003e\n    )}\n  \u003c/Counter.State\u003e\n);\n```\n\n#### Context Provider/Consumer Pattern\n```jsx\nconst Displayer = (props) =\u003e (\n  \u003cCounter.Provider initialValue={5}\u003e\n    \u003cCounter.Consumer\u003e\n      {({ counter: { state, handlers } }) =\u003e (\n        \u003cReact.Fragment\u003e\n          \u003cdiv\u003e{state.count}\u003c/div\u003e\n          \u003cbutton onClick={() =\u003e handlers.decrementBy(1)}\u003eDecrement\u003c/button\u003e\n          \u003cbutton onClick={() =\u003e handlers.incrementBy(1)}\u003eIncrement\u003c/button\u003e\n        \u003c/React.Fragment\u003e\n      )}\n    \u003c/Counter.Consumer\u003e\n  \u003c/Counter.Provider\u003e\n);\n```\n\n#### Custom Hook Pattern\n```jsx\nconst Displayer = (props) =\u003e {\n  const { counter: { state, handlers } } = Counter.useHook({ initialValue: 5 });\n\n  return (\n    \u003cReact.Fragment\u003e\n      \u003cdiv\u003e{state.count}\u003c/div\u003e\n      \u003cbutton onClick={() =\u003e handlers.decrementBy(1)}\u003eDecrement\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e handlers.incrementBy(1)}\u003eIncrement\u003c/button\u003e\n    \u003c/React.Fragment\u003e\n  );\n};\n```\n\n## Code Style Guides\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\n[Prettier](https://prettier.io/) is run as a pre-commit hook to automatically\nmodify staged `.js` and `.jsx` files to adhere to base code style rules defined in the `.prettierrc`.\n\n[Eslint](https://eslint.org/) is also used as an in-editor linter, so be sure to install\nan appropriate [Eslint Plugin](https://eslint.org/docs/3.0.0/user-guide/integrations#editors) for your editor of choice.\nPrettier rules are setup to take precedence and override any conflicting eslint rules.\n\n\n## License\nReact State Patterns is available as open source under the terms of the MIT [license](https://github.com/mcclayton/react-state-patterns/blob/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcclayton%2Freact-state-patterns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcclayton%2Freact-state-patterns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcclayton%2Freact-state-patterns/lists"}