{"id":13781105,"url":"https://github.com/colevoss/react-motive","last_synced_at":"2025-08-22T12:34:17.956Z","repository":{"id":46931502,"uuid":"128090583","full_name":"colevoss/react-motive","owner":"colevoss","description":"Another React state management library using the new Context API","archived":false,"fork":false,"pushed_at":"2022-12-07T11:12:27.000Z","size":944,"stargazers_count":14,"open_issues_count":17,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T18:41:34.715Z","etag":null,"topics":["react","react-context","state-management"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/colevoss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-04T16:34:00.000Z","updated_at":"2023-03-28T11:17:10.000Z","dependencies_parsed_at":"2023-01-24T16:46:05.917Z","dependency_job_id":null,"html_url":"https://github.com/colevoss/react-motive","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/colevoss%2Freact-motive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colevoss%2Freact-motive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colevoss%2Freact-motive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colevoss%2Freact-motive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/colevoss","download_url":"https://codeload.github.com/colevoss/react-motive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248294893,"owners_count":21079997,"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","react-context","state-management"],"created_at":"2024-08-03T18:01:22.961Z","updated_at":"2025-04-10T20:45:52.719Z","avatar_url":"https://github.com/colevoss.png","language":"JavaScript","funding_links":[],"categories":["List","Libraries"],"sub_categories":[],"readme":"# React Motive [![npm](https://img.shields.io/npm/v/react-motive.svg)](https://www.npmjs.com/package/react-motive) [![npm](https://img.shields.io/npm/dm/react-motive.svg)](https://www.npmjs.com/package/react-motive) ![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/react-motive.svg) ![Travis](https://img.shields.io/travis/colevoss/react-motive.svg)\n\nSmall wrapper around the React Context API with actions/dispatch style state management.\n\n## Install\n\n```\nyarn add react-motive\n```\n\n## Example\n\n[![Edit React Motive Counter Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/ll693wn0pl?module=%2Fsrc%2FCounter.js)\n\n```js\nimport React from 'react';\nimport createMotive from 'react-motive';\n\n/**\n * Default State\n */\nconst defaultState = { count: 0 };\n\n/**\n * Actions:\n *\n * Actions don't have to be curried functions if they don't take arguments\n * as long as dispatch is given a function that returns a new slice of state.\n */\nconst increment = () =\u003e ({ count }) =\u003e ({\n  count: count + 1,\n});\n\nconst decrement = () =\u003e ({ count }) =\u003e ({\n  count: count - 1,\n});\n\n/**\n * Create Container\n */\nconst Counter = createMotive(defaultState);\n\n/**\n * Use Consumers\n */\nconst Display = () =\u003e (\n  \u003cCounter.Consumer\u003e\n    {({ state }) =\u003e \u003ch1\u003eCount: {state.count}\u003c/h1\u003e}\n  \u003c/Counter.Consumer\u003e\n);\n\nconst Controls = () =\u003e (\n  \u003cCounter.Consumer\u003e\n    {({ dispatch }) =\u003e (\n      \u003cReact.Fragment\u003e\n        \u003cbutton onClick={() =\u003e dispatch(decrement())}\u003e-\u003c/button\u003e\n        \u003cbutton onClick={() =\u003e dispatch(increment())}\u003e+\u003c/button\u003e\n      \u003c/React.Fragment\u003e\n    )}\n  \u003c/Counter.Consumer\u003e\n);\n\n/**\n * Put it all together\n */\nconst AllTogether = () =\u003e (\n  \u003cCounter.Provider\u003e\n    \u003cDisplay /\u003e\n    \u003cControls /\u003e\n  \u003c/Counter.Provider\u003e\n);\n```\n\n## Documentation\n\n#### `createMotive`\n\n`createMotive` returns an object with a `Provider` component and a `Consumer` component.\n\n```js\nconst defaultState = { count: 1 };\n\nconst { Provider, Consumer } = createMotive(defaultState);\n```\n\n#### `\u003cProvider\u003e`\n\nThe `Provider` is a React component that should wrap all of its corresponding `Consumer` components. This component holds all of the state given from `defaultState` and that is updated later on.\n\n#### `\u003cConsumer\u003e`\n\nThe `Consumer` component is what you can use anywhere as long as it's a child of the corresponding `Provider` component. Use this component to get access to the state of its `Provider` and to dispatch updates to that state.\n\n```js\n\u003cConsumer\u003e\n  {({ state, dispatch }) =\u003e /* ... some react stuff that uses state or dispatch */ }\n\u003c/Consumer\u003e\n```\n\nThis component takes a render prop as its child. This render prop is given an object with the following members in it.\n\n##### `state`\n\nThis is the current state of the corresponding `Provider` component.\n\n#### `dispatch`\n\n`dispatch` should be called with an `action` function. An `action` should return a slice of new state to be merged into the `Provider`'s state.\n\n### Actions\n\nActions are provided with `state` and `dispatch` as arguments. This means you can dispatch other actions from an action if necessary.\n\nAn action must return a partial version of state.\n\n**Pro Tip:** If you need to give actions data, write them as curried functions and call them into `dispatch` with any arugments that they might need.\n\n```js\n/**\n * Basic action\n */\nconst increment = (state) =\u003e ({\n  count: state.count + 1,\n});\n\ndispatch(increment);\n\n/**\n * Curried action that takes arguments\n */\nconst incrementBy = (incrBy) =\u003e (state) =\u003e ({\n  count: state.count + incrBy,\n});\n\ndispatch(incrementBy(2));\n\n/**\n * Action that dispatches another action\n */\nconst delayedIncrement = (state, dispatch) =\u003e {\n  setTimeout(() =\u003e dispatch(incrementBy(2)));\n\n  return {\n    count: state.count + 1,\n  };\n};\n\ndispatch(delayedIncrement);\n```\n\n#### `combineActions`\n\n`combineActions` will take two actions and combine their returned updated pieces of state into one updated piece of state.\n\n```js\nconst defaultState = {\n  a: 0,\n  b: 0,\n};\n\nconst actionA = (state) =\u003e {\n  return {\n    a: state.a + 1,\n  };\n};\n\nconst actionB = (state) =\u003e ({\n  b: state.b + 2,\n});\n\nconst combined = combineActions(actionsA, actionB);\n\nconst resultingState = dispatch(combined);\n\nresultingState === { a: 1, b: 2 };\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolevoss%2Freact-motive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcolevoss%2Freact-motive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolevoss%2Freact-motive/lists"}