{"id":26452050,"url":"https://github.com/zoubingwu/reackt","last_synced_at":"2025-03-18T17:26:02.555Z","repository":{"id":103341723,"uuid":"221051999","full_name":"zoubingwu/reackt","owner":"zoubingwu","description":"The simplest state container built on top of redux and immer to make life easier.","archived":false,"fork":false,"pushed_at":"2020-07-09T11:42:16.000Z","size":61,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-03-23T11:57:49.949Z","etag":null,"topics":["async","immer","reackt","react","redux","state-management"],"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/zoubingwu.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,"governance":null}},"created_at":"2019-11-11T19:14:45.000Z","updated_at":"2021-08-05T09:28:47.000Z","dependencies_parsed_at":"2023-09-20T20:51:42.497Z","dependency_job_id":null,"html_url":"https://github.com/zoubingwu/reackt","commit_stats":null,"previous_names":["shadeofgod/reackt"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoubingwu%2Freackt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoubingwu%2Freackt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoubingwu%2Freackt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoubingwu%2Freackt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zoubingwu","download_url":"https://codeload.github.com/zoubingwu/reackt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244227400,"owners_count":20419239,"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":["async","immer","reackt","react","redux","state-management"],"created_at":"2025-03-18T17:26:01.846Z","updated_at":"2025-03-18T17:26:02.511Z","avatar_url":"https://github.com/zoubingwu.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reackt [![Actions Status](https://github.com/shadeofgod/reackt/workflows/test/badge.svg)](https://github.com/shadeofgod/reackt/actions) ![](https://img.shields.io/npm/l/reakt)\n\nReackt is a tiny state container built on top of [redux](https://github.com/reduxjs/redux) and [immer](https://github.com/immerjs/immer).\n\nIt helps you build your application without worrying about all the boilerplate codes on defining action types or action creators like when using redux. You only have to define your state and how to update it and leave other thing to reackt.\n\nReackt is built on top of redux, you have all the benefits with redux like time-travel debugging, easy to implement undo/redo, state persistence, etc.\n\nBut unlike redux's pure and synchronous reducer, you can do whatever you want in reackt's update functions, **async or sync**! You no longer need other middlewares such as redux-thunk, redux-saga or redux-observable to handle all the asynchronous tasks for you.\n\nReackt makes writing GUI back to the simplest model:\n\n1. User interaction triggers some kind of event.\n2. Event triggers a function call to compute and update the app state.\n3. The state changes trigger UI re-render so users can have feedback to respond their interaction.\n\nYou shouldn't have to consider all those concepts like reducers, actions, action types, action creators in your brain now, reackt just handles it internally for you!\n\nReackt also has built-in immer support, you can just update your state in a mutable way but have all the benefits of immutable state!\n\n# Getting Started\n\n### Install\n\n```sh\nnpm install reackt redux immer\n```\n\nor\n\n```sh\nyarn add reackt redux immer\n```\n\n### Usage\n\nreackt **only provides one simple API**: `createStore`.\n\nIt has pretty much the same signature like redux's createStore except its first argument is an object describing your modular models and other options like below.\n\n```ts\nfunction createStore(\n  { models, onError = noop, useImmer = true },\n  preloadState,\n  enhancers\n): Store {\n  //...\n}\n```\n\nLet's try a counter example, we only have to define our state and how to update it, no more action, action types or action creators to worry about!\n\n**store.js**\n\n```js\nimport createStore from 'reackt';\n\nconst counter = {\n  state: 0,\n  updates: setState =\u003e ({\n    increment: () =\u003e\n      setState(state =\u003e {\n        state = state + 1; // setState is like immer's produce, you can just mutate your state here\n      }),\n  }),\n};\n\nexport const store = createStore({\n  models: { counter },\n});\n\n// it returns a redux store with extra enhancement,\n// now you can just call your update functions thru dispatch\nstore.getState(); // -\u003e { counter: 0 }\nstore.dispatch.counter.increment();\nstore.getState(); // -\u003e { counter: 1 }\n```\n\nYour update function can also handle async task like this:\n\n```js\nconst counter = {\n  state: 0,\n  updates: setState =\u003e {\n    const increment = () =\u003e\n      setState(state =\u003e {\n        state = state + 1;\n      });\n    const incrementAsync = async () =\u003e {\n      await delay();\n      increment();\n    };\n\n    return {\n      increment,\n      incrementAsync,\n    };\n  },\n};\n\n// now you can use it just like normal async function\nawait store.dispatch.counter.incrementAsync();\nstore.getState(); // -\u003e returns { counter: 1 } after delay\n```\n\nSince we build on top of redux and redux is view-layer agnostic, we can use any other UI library.\n\nFor react, we can use react-redux to connect the state to our view components. Using hooks API to make it even more enjoyable.\n\n**index.js**\n\n```js\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport { Provider, useSelector, useDispatch } from 'react-redux';\n\nimport { store } from './store';\n\nfunction App() {\n  const count = useSelector(state =\u003e state.counter);\n  const {\n    counter: { increment, incrementAsync },\n  } = useDispatch();\n\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003e{count}\u003c/h1\u003e\n      \u003cbutton onClick={increment}\u003eincrement\u003c/button\u003e\n      \u003cbutton onClick={incrementAsync}\u003eincrement async\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nReactDOM.render(\n  \u003cProvider store={store}\u003e\n    \u003cApp /\u003e\n  \u003c/Provider\u003e,\n  document.getElementById('app')\n);\n```\n\nYou can [check the full counter example on codesandbox.](https://codesandbox.io/s/github/shadeofgod/reackt/tree/master/examples/counter?fontsize=14\u0026hidenavigation=1\u0026theme=dark)\n\nThere is also [an advanced github search example here!](https://codesandbox.io/s/github/shadeofgod/reackt/tree/master/examples/search?fontsize=14\u0026hidenavigation=1\u0026theme=dark)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzoubingwu%2Freackt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzoubingwu%2Freackt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzoubingwu%2Freackt/lists"}