{"id":21668678,"url":"https://github.com/lucasmrdt/nedux","last_synced_at":"2025-04-12T02:22:40.796Z","repository":{"id":36467171,"uuid":"226185470","full_name":"lucasmrdt/nedux","owner":"lucasmrdt","description":"📦 State manager - the next redux","archived":false,"fork":false,"pushed_at":"2023-01-05T02:26:52.000Z","size":288,"stargazers_count":41,"open_issues_count":8,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T02:22:31.199Z","etag":null,"topics":["functional","nedux","next-redux","state","state-management","store","typescript"],"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/lucasmrdt.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-12-05T20:41:38.000Z","updated_at":"2023-05-23T08:21:14.000Z","dependencies_parsed_at":"2023-01-17T01:45:23.053Z","dependency_job_id":null,"html_url":"https://github.com/lucasmrdt/nedux","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/lucasmrdt%2Fnedux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasmrdt%2Fnedux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasmrdt%2Fnedux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasmrdt%2Fnedux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucasmrdt","download_url":"https://codeload.github.com/lucasmrdt/nedux/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248506121,"owners_count":21115384,"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":["functional","nedux","next-redux","state","state-management","store","typescript"],"created_at":"2024-11-25T12:17:15.304Z","updated_at":"2025-04-12T02:22:40.760Z","avatar_url":"https://github.com/lucasmrdt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nedux - The `n`ext r`edux`\n\n![typescript](https://img.shields.io/badge/-typescript-blueviolet) [![version](https://img.shields.io/badge/version-beta-blue)](https://www.npmjs.com/package/nedux) [![size](https://img.shields.io/bundlephobia/minzip/nedux?color=green\u0026label=size)](https://www.npmjs.com/package/nedux)\n\n\u003e Why do you waste your time by creating actions/reducers/containers/sagas/... ? \\\n\u003e **Just create a store and that's it !**\n\n## 📦 Installation\n\n```bash\nnpm install nedux --save\n```\n\n## 🧲 Use `Nedux` with ...\n\n| library |                        provider                         |\n| :-----: | :-----------------------------------------------------: |\n|  React  | [react-nedux](https://github.com/lucasmrdt/react-nedux) |\n|  VueJS  |                         `todo`                          |\n| Angular |                         `todo`                          |\n\n## 😍 Examples\n\n|         Name         |                  Source                   |                                                    Codesandbox                                                     |\n| :------------------: | :---------------------------------------: | :----------------------------------------------------------------------------------------------------------------: |\n|     ✅ Todo List     |         [here](./examples/todos)          |             [here](https://codesandbox.io/s/nedux-todos-nm8j0?fontsize=14\u0026hidenavigation=1\u0026theme=dark)             |\n| 🔎 Logger Middleware |   [here](./examples/logger-middleware)    |           [here](https://codesandbox.io/s/eloquent-black-hbmut?fontsize=14\u0026hidenavigation=1\u0026theme=dark)            |\n|      🎛 Counter       | [here](./examples/counter-nedux-vs-redux) | [here](https://codesandbox.io/s/counter-nedux-vs-redux-n34b2?fontsize=14\u0026hidenavigation=1\u0026theme=dark\u0026view=preview) |\n\n## 💻 Basic Example\n\n### Use it with Typescript ♥️\n\n```typescript\nimport { createStore } from 'nedux';\n\ninterface Todo {\n  id: number;\n  text: string;\n  completed: boolean;\n}\n\nenum Filter {\n  ShowAll = 'ShowAll',\n  ShowCompleted = 'ShowCompleted',\n  ShowActive = 'ShowActive',\n}\n\n// Create the store\nconst todoStore = createStore({\n  todos: [] as Todo[],\n  filter: Filter.ShowAll,\n});\n\n// You can subscribe to field update.\ntodoStore.subscribe('filter', newFilter =\u003e {\n  console.log(`filter has changed with ${newFilter}`);\n});\n\n// You can get a value.\ntodoStore.get('filter');\n// └\u003e 'ShowAll'\n\n// You can override a value.\ntodoStore.set('filter', Filter.ShowCompleted);\n\n// Or extends value by the previous one.\ntodoStore.set('todos', todos =\u003e [\n  ...todos,\n  { id: 1, text: 'test', completed: false },\n]);\n\n// And that's it !\n```\n\n### Or simply with Javascript\n\n```javascript\nimport { createStore } from 'nedux';\n\nconst todoStore = createStore({\n  todos: [],\n  filter: 'ShowAll',\n});\n\ntodoStore.subscribe('filter', newFilter =\u003e {\n  console.log(`filter has changed with ${newFilter}`);\n});\n\ntodoStore.get('filter');\n\ntodoStore.set('filter', 'ShowCompleted');\ntodoStore.set('todos', todos =\u003e [\n  ...todos,\n  { id: 1, text: 'test', completed: false },\n]);\n```\n\n## 📜 Documentation\n\n### `Import`\n\n```javascript\n// ES6\nimport { createStore } from 'nedux';\n\n// ES5\nvar createStore = require('nedux').createStore;\n```\n\n### `createStore(initialState, [middlewares])`\n\nCreates a Nedux store with the shape of the `initialState`.\n\n|   argument    | required |             type             | description                                                                                         |\n| :-----------: | :------: | :--------------------------: | :-------------------------------------------------------------------------------------------------- |\n| `initalState` |    ✅    |           `object`           | The intial state of your store.                                                                     |\n| `middlewares` |    ❌    | [Middleware](#middlewares)[] | Middlewares are used to enhance your store see the [middleware section](#middlewares) to know more. |\n\n### `store`\n\nThe `store` object created by `createStore` it'll allow you to interact with your store.\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003estore.get(key)\u003c/b\u003e\u003c/summary\u003e\n\u003cbr\u003e\n\n| argument | required |   type   | description                               |\n| :------: | :------: | :------: | :---------------------------------------- |\n|  `key`   |    ✅    | `string` | The key of the store that you want to get |\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003estore.set(key, value)\u003c/b\u003e\u003c/summary\u003e\n\u003cbr\u003e\n\n| argument | required |                     type                      | description                                    |\n| :------: | :------: | :-------------------------------------------: | :--------------------------------------------- |\n|  `key`   |    ✅    |                   `string`                    | The key of the store that you want to override |\n| `value`  |    ✅    | `any` \u003cbr /\u003eor\u003cbr /\u003e`(prevValue: any) =\u003e any` | The new value of the key                       |\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003estore.subscribe(key, observer)\u003c/b\u003e\u003c/summary\u003e\n\u003cbr\u003e\n\n|  argument  | required |                                                        type                                                         | description                                                                                                      |\n| :--------: | :------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------- |\n|   `key`    |    ✅    |                                                      `string`                                                       | The key of the store that you'll subscribe to changes. (give a value of `''` will subscribe to all keys changes) |\n| `observer` |    ✅    | [observer](http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html) \u003cbr /\u003e or \u003cbr /\u003e `(value: any) =\u003e any` | An rxjs observer or a simple callback which will be fired when the store has been updated for the given key      |\n\n\u003c/details\u003e\n\n\u003ca id=\"middlewares\"\u003e\u003c/a\u003e\n\n## ⚓️ Middlewares\n\nMiddleware is the suggested way to extend Nedux with custom functionality. The _created store_ is provided to each middleware. It's easy to `subscribe`/`get`/`set` value to the store inside your middleware. The key feature of middleware is that it is composable. Multiple middleware can be combined together, where each middleware requires no knowledge of what comes before or after it in the chain.\n\n|                           Middleware                           |              Description              |\n| :------------------------------------------------------------: | :-----------------------------------: |\n| [🔒 nedux-persist](https://github.com/lucasmrdt/nedux-persist) | Allow you to persist your nedux store |\n\n### Basic Logger Middleware\n\n```javascript\nimport { createStore } from 'nedux';\n\nconst loggerMiddleware = store =\u003e\n  // we subscribe to all modifications\n  store.subscribe('', value =\u003e console.log(value));\n\nconst store = createStore(\n  {\n    a: 0,\n    b: 'b',\n  },\n  [loggerMiddleware],\n);\n\nstore.set('b', 'a');\nstore.set('a', 1);\nstore.set('a', a =\u003e a * 2);\nstore.set('b', 'not b');\n```\n\n## 🏗 Advised Structure\n\n\u003e It usually a good idea to keep the store as small as possible. You can manage your application by structure it as services. Each service will have its own store _(if it's needed)_\n\n```bash\nmy-service\n├── components # Your components.\n│   ├── AddTodo.tsx\n│   ├── App.tsx\n│   ├── FilterLink.tsx\n│   ├── Footer.tsx\n│   ├── Link.tsx\n│   ├── Todo.tsx\n│   └── TodoList.tsx\n├── controler.ts # Where you wrap your business logic (link between api/store/ui)\n├── index.tsx # Where you export elements to other services.\n├── store.ts # Where the store is created with the initial state.\n└── types.ts # Where you put your service types.\n```\n\n## 🚀 Why choose `Nedux` over `Redux` ?\n\n- [x] No more actions\n- [x] No more dispatch\n- [x] No more reducers\n- [x] No more provider\n- [x] Fully functionnal usage\n- [x] Easiest to understand\n- [x] No \"magical\" effect _(all is traceable)_\n- [x] No need to use external tools to debug _(again all is traceable)_\n- [x] Easiest to learn\n- [x] Fully typed _(if you're coding in typescript you will ♥️ it !)_\n- [x] Less code to write\n- [x] Faster and lighter _(no [react context](https://reactjs.org/docs/context.html), no [HOC](https://reactjs.org/docs/higher-order-components.html))_\n\n\u003e **You just write less to do the same.**\n\n### 🥊 [Redux todos](https://github.com/reduxjs/redux/tree/master/examples/todos) VS [Nedux todos](./examples/todos) _(same code)_\n\n\u003e Feel free to inspect the structure of both of them ([Redux](https://github.com/reduxjs/redux/tree/master/examples/todos) and [Nedux](./examples/todos)) and how Nedux is implemented.\n\n|                       |   Redux    |   Nedux   | Diff _(less is better)_ |\n| :-------------------: | :--------: | :-------: | :---------------------: |\n|    number of files    |    `13`    |   `11`    |        `-15.4%`         |\n|    number of lines    |   `224`    |   `174`   |        `-22.3%`         |\n| number of characters  |   `4343`   |  `3298`   |        `-24.0%`         |\n| time for first render | `~10.5 ms` | `~8.5 ms` |        `-23.5%`         |\n|       add todo        | `~0.8 ms`  | `~0.6 ms` |        `-33.3%`         |\n\n### 🥊 [Redux Counter](./examples/counter) VS [Nedux Counter](./examples/counter) _(same code)_\n\n\u003e Again feel free to test it yourself [here](https://codesandbox.io/s/counter-nedux-vs-redux-n34b2?fontsize=14\u0026hidenavigation=1\u0026theme=dark\u0026view=preview).\n\n|    Render time    |  Redux   |  Nedux   | Diff _(less is better)_ |\n| :---------------: | :------: | :------: | :---------------------: |\n| with _9999_ items | `0.743s` | `0.481s` |        `-35.3%`         |\n\n### 🏗 Structure\n\n```bash\n# Redux Todos\n├── actions\n│   └── index.js\n├── components\n│   ├── App.js\n│   ├── Footer.js\n│   ├── Link.js\n│   ├── Todo.js\n│   └── TodoList.js\n├── containers\n│   ├── AddTodo.js\n│   ├── FilterLink.js\n│   └── VisibleTodoList.js\n├── index.js\n└── reducers\n    ├── index.js\n    ├── todos.js\n    └── visibilityFilter.js\n```\n\n```bash\n# Nedux Todos\n├── components\n│   ├── AddTodo.tsx\n│   ├── App.tsx\n│   ├── FilterLink.tsx\n│   ├── Footer.tsx\n│   ├── Link.tsx\n│   ├── Todo.tsx\n│   └── TodoList.tsx\n├── controler.ts\n├── index.tsx\n├── store.ts\n└── types.ts\n```\n\n### 🧩 Scripts used\n\n```bash\n# Compute number of files\nfind $SRC_FOLDER -type f | wc -l\n\n# Compute number of lines\nfind $SRC_FOLDER -type f -exec cat {} \\; | grep -v -e '^$' | grep -v -e '^//' | wc -l\n\n# Compute number of characters\nfind $SRC_FOLDER -type f -exec cat {} \\; | grep -v -e '^$' | grep -v -e '^//' | tr -d '[:space:] ' | wc -c\n```\n\n### 🔎 Profiling method\n\nProfiling is made with [React Profiling](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) following this configuration :\n\n|                        |                                 |\n| :--------------------: | :-----------------------------: |\n|     **Navigator**      | Chrome _78.0.3904.108 (64-bit)_ |\n| **Profiling Software** |  React Developer Tools _4.2.1_  |\n|         **OS**         |    MacOS Catalina _10.15.1_     |\n|       **Model**        |   MacBook Pro (15-inch, 2018)   |\n|     **Processor**      |  2.2 GHz 6-Core Intel Core i7   |\n|       **Memory**       |       16 GB 2400 MHz DDR4       |\n|      **Graphic**       | Intel UHD Graphics 630 1536 MB  |\n\n## 📋 Todos\n\n- [x] Add sandbox for each examples\n- [ ] Add tests\n- [ ] Be more accurate on performance comparison\n- [ ] Add more examples\n- [ ] Type cleaning\n- [ ] Add CI\n- [ ] Add VueJS connector\n- [ ] Add Angular connector\n\n## 🙋🏼 Contributions\n\nAll [Pull Requests](https://github.com/lucasmrdt/nedux/compare?expand=1), [Issues](https://github.com/lucasmrdt/nedux/issues) and [Discussions](https://github.com/lucasmrdt/nedux/issues) are welcomed !\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasmrdt%2Fnedux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucasmrdt%2Fnedux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasmrdt%2Fnedux/lists"}