{"id":16295687,"url":"https://github.com/hamlim/react-state-reducer","last_synced_at":"2025-09-21T23:52:16.210Z","repository":{"id":29586672,"uuid":"122144070","full_name":"hamlim/react-state-reducer","owner":"hamlim","description":"Simple React state management using createContext","archived":false,"fork":false,"pushed_at":"2025-01-12T02:54:59.000Z","size":2425,"stargazers_count":2,"open_issues_count":4,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-13T11:39:16.704Z","etag":null,"topics":["create-react-app","createcontext","react","state-management"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/github/hamlim/react-state-reducer","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/hamlim.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-20T01:49:03.000Z","updated_at":"2025-01-12T02:54:22.000Z","dependencies_parsed_at":"2025-04-10T11:10:14.910Z","dependency_job_id":"98f8d789-91b5-4c85-8a06-e2f6435420b7","html_url":"https://github.com/hamlim/react-state-reducer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hamlim/react-state-reducer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hamlim%2Freact-state-reducer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hamlim%2Freact-state-reducer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hamlim%2Freact-state-reducer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hamlim%2Freact-state-reducer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hamlim","download_url":"https://codeload.github.com/hamlim/react-state-reducer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hamlim%2Freact-state-reducer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276324427,"owners_count":25622504,"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","status":"online","status_checked_at":"2025-09-21T02:00:07.055Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["create-react-app","createcontext","react","state-management"],"created_at":"2024-10-10T20:19:31.569Z","updated_at":"2025-09-21T23:52:16.155Z","avatar_url":"https://github.com/hamlim.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React-State-Reducer\n\nA simple (non-feature complete) ~clone~ reimplementation of [Redux](https://redux.js.org) built using React 16.3's `createContext`.\n\n### Example:\n\n```jsx\nimport React, { Fragment } from 'react'\nimport createStore from 'react-state-reducer'\n\nconst INITIAL_STATE = {\n  count: 0,\n}\n\nconst counterReducer = action =\u003e (\n  state = INITIAL_STATE,\n) =\u003e {\n  switch (action.type) {\n    case 'INC':\n      return { count: state.count + 1 }\n    case 'DEC':\n      return { count: state.count - 1 }\n    default:\n      return state\n  }\n}\n\nconst { Provider, Consumer } = createStore(counterReducer)\n\nexport default () =\u003e (\n  \u003cProvider\u003e\n    \u003cConsumer\u003e\n      {({ count, dispatch }) =\u003e (\n        \u003cFragment\u003e\n          \u003cbutton onClick={() =\u003e dispatch({ type: 'DEC' })}\u003e\n            -\n          \u003c/button\u003e\n          {count}\n          \u003cbutton onClick={() =\u003e dispatch({ type: 'INC' })}\u003e\n            +\n          \u003c/button\u003e\n        \u003c/Fragment\u003e\n      )}\n    \u003c/Consumer\u003e\n  \u003c/Provider\u003e\n)\n```\n\n## API:\n\nThere are two core parts of react-state-reducer's API that should be kept in mind.\n\n### Reducers:\n\nThe first is the `reducer`. A `reducer` is a higher order function (meaning it returns a function), that first accepts an `action` and returns a function that accepts the current state (and optionally any props provided to the `\u003cProvider\u003e`). This returned function should then handle returning the updated state.\n\nThat was a lot of different words describing what this is, lets look at some code to walk through this.\n\n1.  Lets start with the higher order function:\n\n```js\nconst myReducer = someAction =\u003e {\n  return (state) =\u003e {\n    ...\n  }\n}\n```\n\nThis function accepts a single argument (`someAction`) and returns a function. Which in turn accepts a single argument called `state`. This is often written as the following:\n\n```js\nconst myReducer = action =\u003e state =\u003e { ... };\n```\n\n2.  Handling updates within the returned function:\n\n```js\nconst myReducer = action =\u003e state =\u003e {\n  if (action === 'SOME_UPDATE') {\n    return {\n      ...state,\n      someKey: '🆒',\n    }\n  }\n}\n```\n\nSome notes with this implementation above:\n\n* It doesn't follow the generic [Redux](https://redux.js.org/basics/reducers) reducer concept of using a `switch` you can handle writing this function however you would like (using `switch`, or using an if/else)\n\n* Right now we are implicitly returning `undefined` if `action` does not equal `'SOME_UPDATE'`, while this is valid, you should make sure to at least handle returning the initial state if the action is the following shape:\n\n```js\n{type: '@@INIT', payload: null}\n```\n\nWhat this looks like in practice:\n\n```js\nconst todoReducer = action =\u003e (state = { todos: [] }) =\u003e {\n  switch (action.type) {\n    case 'ADD_TODO': {\n      return {\n        todos: [\n          ...state.todos,\n          {\n            id: state.todos.length,\n            completed: false,\n            text: action.payload,\n          },\n        ],\n      }\n    }\n    case 'CHECK_TODO': {\n      return {\n        todos: todos.map(todo =\u003e {\n          if (todo.id === action.payload) {\n            return {\n              ...todo,\n              completed: !todo.completed,\n            }\n          } else {\n            return todo\n          }\n        }),\n      }\n    }\n    default:\n      return state\n  }\n}\n```\n\n### `createStore`:\n\n`createStore` is the main export of react-state-reducer, it is a function that accepts a `reducer` as an argument. It calls the reducer with the initialization action:\n\n```js\nyourReducer({ type: '@@INIT', payload: null })(null)\n```\n\nand then uses the result of calling the reducer as the initial state for the store. `createStore` then returns an object with the following:\n\n```js\n{\n  Provider: Node,\n  Consumer: Node\n}\n```\n\n#### `Provider`\n\nThe Provider component exposes two props, the first is `children` which can be a single component, or many components.\n\nThe second prop is `onUpdate` which is a function that will be called after each state update happens, it is called with the updated state.\n\n```jsx\n\u003cProvider\n  onUpdate={newState =\u003e {\n    /* Maybe sync state to localStorage, or something else */\n  }}\n\u003e\n  \u003cApp /\u003e\n\u003c/Provider\u003e\n```\n\n#### `Consumer`\n\nThe Consumer component has one core prop, `children`, children is a function that gets called with an object with the following keys:\n\n* `dispatch`\n* top level keys from state\n\nFor example if your state shape looks like this:\n\n```js\n{\n  todos: [],\n  text: ''\n}\n```\n\nthe consumer children function would look like the following:\n\n```jsx\n\u003cConsumer\u003e\n  {({\n    dispatch,\n    todos,\n    text\n  }) =\u003e (\n    ...\n  )}\n\u003c/Consumer\u003e\n```\n\nConsumer also optionally supports a `selector` prop, which can either take in an array of functions or a single function to select your slice of state you care about:\n\n```jsx\n\u003cConsumer selector={s =\u003e s.todos}\u003e\n  {({ dispatch }, todos) =\u003e {\n    /* */\n  }}\n\u003c/Consumer\u003e\n```\n\n### Redux\n\nThis library is highly influenced by all the great work put into Redux and React-Redux. For some more information on the differences between this library and Redux see [redux](./docs/redux.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhamlim%2Freact-state-reducer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhamlim%2Freact-state-reducer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhamlim%2Freact-state-reducer/lists"}