{"id":21977366,"url":"https://github.com/zmitry/okdux","last_synced_at":"2025-04-28T16:43:11.215Z","repository":{"id":57314005,"uuid":"131039569","full_name":"zmitry/okdux","owner":"zmitry","description":"redux made ok 👌","archived":false,"fork":false,"pushed_at":"2023-07-04T19:48:26.000Z","size":1080,"stargazers_count":16,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-21T13:52:33.757Z","etag":null,"topics":["mobx","react-redux","redux"],"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/zmitry.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-25T17:13:09.000Z","updated_at":"2023-07-04T19:47:44.000Z","dependencies_parsed_at":"2024-08-21T22:18:16.248Z","dependency_job_id":null,"html_url":"https://github.com/zmitry/okdux","commit_stats":null,"previous_names":["zhdmitry/okdux"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitry%2Fokdux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitry%2Fokdux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitry%2Fokdux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitry%2Fokdux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zmitry","download_url":"https://codeload.github.com/zmitry/okdux/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251347770,"owners_count":21575145,"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":["mobx","react-redux","redux"],"created_at":"2024-11-29T16:14:26.233Z","updated_at":"2025-04-28T16:43:11.196Z","avatar_url":"https://github.com/zmitry.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Okdux 👌\n\n[![CircleCI](https://circleci.com/gh/zhDmitry/restate.svg?style=svg)](https://circleci.com/gh/zhDmitry/okdux)\n[![NPM Downloads](https://img.shields.io/npm/dm/okdux.svg?style=flat)](https://www.npmjs.com/package/okdux)\n\nThis lib was created for reducing pain from redux boilerplate.\n\n---\n\n## Installation\n\n```bash\nnpm install --save okdux\n```\n\nor\n\n```bash\nyarn add okdux\n```\n\n## Usage\n\n```js\nimport { createStore } from \"redux\";\nimport { connect } from \"react-redux\";\n\n\nimport { createActions, createState, build } from \"okdux\";\n\n\nconst actions = createActions({\n  inc: build.action\u003cstring\u003e()\n});\n\nconst counterState = createState(0);\n// different types of counters\nconst state = createState({ counter: countersState });\n\ncounterState.on(actions.inc, (state, p) =\u003e {\n  return state + 1;\n});\n\n//[optional]auto bind all actions to redux\n//store is redux store\nstate.createStore((reducer)=\u003e createStore(reducer, {}));\n// or\nconst store = createStore(state.reducer, {});\nstate.use(store.dispatch);\n\ncountersState.select(store.getState()); // will return state from root\ncountersState.select(store.getState()); // will return state from root\n\n// select only counter from root state\n// this component will be reuseable and you won't care about where your reducer are placed\n// also you will get types suggestions\nconst enhancer = connect(countersState.select(counter=\u003e({ counter })))\n\n\n// dispatch actions\n// all actions are autobinded to store after using .use action\n// you can assign one action to multiple stores\n// to access plain action call inc.raw();\n// actions are autobinded in case of\ninc(1);\ninc(2);\ninc(2);\ninc(3);\ninc(8);\n```\n\n## API\n\n### `createState({ //plain obj or different state }) =\u003e StateBuilder`\n\ncreate state from plain object or compose from different state\n\n```js\nconst counter = createState(0);\n\nconst state = createState({ counter });\n```\n\nALERT: YOU CAN PASS to createState either plain obj or map of states\n\nthis is ok\n\n```js\nconst counter = createState(0);\nconst counter2 = createState(0);\n\nconst state = createState({ counter, counter2 });\n```\n\nthis is not ok\n\n```js\nconst counter = createState(0);\nconst counter2 = createState(0);\n\nconst state = createState({ counter, counter2, name: \"6\" /* not ok*/ });\nconst state = createState({ counter, counter2, name: createState(\"name\") }); // this is ok\n```\n\n### StateBuilder\n\n### `StateBuilder.on(Action:Action, handler:(substate: any, ActionPayload)=\u003enew substate)`\n\nAdd handler to substate\nIt's like building reducer but with using `.on` instead of switch cases\nin handler as second argument you will get action payload and you have to return new state\n\n### `StateBuilder.select(RootStateObject)=\u003e state`\n\nselects state related to your state builder\n\n### `StateBuilder.select((subState)=\u003emappedState)=\u003e mappedState`\n\nstate with map is equivalent to mapFn(StateBuilder.select({}));\n\nit will return substate related to some stateBuilder\nExample:\n\n```js\n// somewhere in state file;\nconst counterState = createState(0);\n\n//somewhere in component\n// now you can select your counter state and don't care about counter placement in store\nconst enhancer = connect(countersState.select(counter =\u003e ({ counter })));\n```\n\nALERT: you can have only one stateBuilder mounded to root state\n\n```js\nconst st = createState(2);\nconst rootSTate = createState({\n  st,\n  st2: st\n}); // not ok\nconst makeSt = () =\u003e createState(2);\nconst rootSTate = createState({\n  st: makeSt(),\n  st2: makeSt()\n}); // ok\n```\n\n### `StateBuilder.reducer: PlainReducer`\n\nreducer property it's encapsulated reducer inside state builder\n\n### `StateBuilder.use(dispatchFn): void`\n\nmakes all actions binded using `on` handler autobinded to this function\nso you won't have to use mapDispatchToProps\n\n### `StateBuilder.createState(createStoreFn): store`\n\nsame as use\n\nexample\n\n```js\nconst state = createState(0);\nstate.createStore(reducer =\u003e createStore(reducer, {}));\n// or simpler\nstate.createStore(createStore);\n```\n\n### `StateBuilder.reset(action): StateBuilder`\n\nreset reducer value to default\nsame as `state.on(action, ()=\u003einitialValue)`\n\n### createActions({ [string]: ActionFactory })\n\nexamples\n\n```js\nimport { build, createState, createApi } from \"okdux\";\nconst counter = createState(0);\n\nconst actions = createApi(counter, {\n  increment(state, payload) {\n    return { ...state, payload };\n  },\n  decrement(state, payload) {\n    return { ...state, payload };\n  }\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmitry%2Fokdux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzmitry%2Fokdux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmitry%2Fokdux/lists"}