{"id":13808974,"url":"https://github.com/timdeschryver/ngrx-immer","last_synced_at":"2025-05-16T06:06:44.343Z","repository":{"id":40768882,"uuid":"322861487","full_name":"timdeschryver/ngrx-immer","owner":"timdeschryver","description":"Immer wrappers around NgRx methods createReducer, on, and ComponentStore","archived":false,"fork":false,"pushed_at":"2025-01-03T07:42:12.000Z","size":54,"stargazers_count":122,"open_issues_count":0,"forks_count":7,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-01T22:36:49.676Z","etag":null,"topics":["angular","immer","ngrx","state"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ngrx-immer","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/timdeschryver.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,"zenodo":null}},"created_at":"2020-12-19T14:05:58.000Z","updated_at":"2025-03-04T14:21:06.000Z","dependencies_parsed_at":"2024-05-17T17:42:41.238Z","dependency_job_id":"e98c3e5a-6e82-41ba-bea7-7568d5d0594d","html_url":"https://github.com/timdeschryver/ngrx-immer","commit_stats":{"total_commits":19,"total_committers":2,"mean_commits":9.5,"dds":"0.052631578947368474","last_synced_commit":"61b281005dae4d1d30440b0c4c4ae2dc410b1a98"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timdeschryver%2Fngrx-immer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timdeschryver%2Fngrx-immer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timdeschryver%2Fngrx-immer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timdeschryver%2Fngrx-immer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timdeschryver","download_url":"https://codeload.github.com/timdeschryver/ngrx-immer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253817590,"owners_count":21969007,"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":["angular","immer","ngrx","state"],"created_at":"2024-08-04T01:01:56.788Z","updated_at":"2025-05-16T06:06:39.331Z","avatar_url":"https://github.com/timdeschryver.png","language":"TypeScript","funding_links":[],"categories":["State Management"],"sub_categories":["NgRx"],"readme":"# ngrx-immer\n\n\u003e Immer wrappers around NgRx methods to simplify mutating state\n\n\u003c!-- TOC --\u003e\n* [ngrx-immer](#ngrx-immer)\n  * [Installation](#installation)\n  * [Functions](#functions)\n    * [`createImmerReducer` (@ngrx/store)](#createimmerreducer-ngrxstore)\n    * [`immerOn` (@ngrx/store)](#immeron-ngrxstore)\n    * [`ImmerComponentStore` (@ngrx/component-store)](#immercomponentstore-ngrxcomponent-store)\n    * [`immerPatchState` (@ngrx/signals)](#immerpatchstate-ngrxsignals)\n    * [`immerReducer`](#immerreducer)\n  * [FAQ](#faq)\n  * [Resources](#resources)\n\u003c!-- TOC --\u003e\n\n## Installation\n\n```bash\nnpm install ngrx-immer\n```\n\n\u003e Do not forget to install immer\n\n## Functions\n\n### `createImmerReducer` (@ngrx/store)\n\nCreates an NgRx reducer, but allows you to mutate state without having to use to spread operator.\n\n- Use it when you want to go Immer all the way\n- Caveat, you have to return the state with each `on` method\n\n```ts\nimport { createImmerReducer } from 'ngrx-immer/store';\n\nconst todoReducer = createImmerReducer(\n\t{ todos: [] },\n\ton(newTodo, (state, action) =\u003e {\n\t\tstate.todos.push({ text: action.todo, completed: false });\n\t\treturn state;\n\t}),\n\ton(completeTodo, (state, action) =\u003e {\n\t\tstate.todos[action.index].completed = true;\n\t\treturn state;\n\t}),\n);\n```\n\n### `immerOn` (@ngrx/store)\n\nCreates an NgRx reducer, but allows you to mutate state without having to use to spread operator.\n\n- Use it when you want to go sprinkle a little bit of Immer for more complex cases\n\n```ts\nimport { immerOn } from 'ngrx-immer/store';\n\nconst todoReducer = createReducer(\n\t{ todos: [] },\n\ton(newTodo, (state, action) =\u003e {\n\t\treturn {\n\t\t\t...state,\n\t\t\ttodos: [...state.todos, action.todo],\n\t\t};\n\t}),\n\timmerOn(completeTodo, (state, action) =\u003e {\n\t\tstate.todos[action.index].completed = true;\n\t}),\n);\n```\n\n### `ImmerComponentStore` (@ngrx/component-store)\n\nWraps Immer around the Component Store `updater` and `setState` methods.\n\n```ts\nimport { ImmerComponentStore } from 'ngrx-immer/component-store';\n\n@Injectable()\nexport class MoviesStore extends ImmerComponentStore\u003cMoviesState\u003e {\n\tconstructor() {\n\t\tsuper({ movies: [] });\n\t}\n\n\treadonly addMovie = this.updater((state, movie: Movie) =\u003e {\n\t\tstate.movies.push(movie);\n\t});\n}\n```\n\n### `immerPatchState` (@ngrx/signals)\n\n\u003e [!IMPORTANT]  \n\u003e Because `@ngrx/signals` is in developer preview, the `immerPatchState` function is also in developer preview. It is ready to try, but may change before becoming stable.\n\nProvides an Immer-version of the `patchState` function from the `@ngrx/signals` package. In addition to partial state objects and updaters that update the state immutably, it accepts updater functions that update the state in a mutable manner. Similar to `patchState`, the `immerPatchState` function can be used to update the state of both SignalStore and SignalState.\n\n```ts\nconst UserStore = signalStore(\n\twithState({\n\t\tuser: { firstName: 'Konrad', lastName: 'Schultz' },\n\t\taddress: { city: 'Vienna', zip: '1010' },\n\t}),\n\twithMethods((store) =\u003e ({\n\t\tsetLastName(lastName: string): void {\n\t\t\timmerPatchState(store, (state) =\u003e {\n\t\t\t\tstate.user.lastName = lastName;\n\t\t\t});\n\t\t},\n\t\tsetCity(city: string): void {\n\t\t\timmerPatchState(store, (state) =\u003e {\n\t\t\t\tstate.address.city = city;\n\t\t\t});\n\t\t},\n\t}))\n);\n```\n\nPlease note, that the updater function can only mutate a change without returning it or return an immutable\nstate without mutable change.\n\nThis one is going to throw a runtime error:\n\n```ts\n// will throw because of both returning and mutable change\nimmerPatchState(userStore, (state) =\u003e {\n\tstate.name.lastname = 'Sanders'; // mutable change\n\treturn state; // returning state\n});\n```\n\n### `immerReducer`\n\nInspired by [Alex Okrushko](https://twitter.com/alexokrushko), `immerReducer` is a reducer method that uses the Immer `produce` method.\nThis method is used by all the methods in `ngrx-immer` provides.\n\n## FAQ\n\n- See the Immer docs, [Update patterns](https://immerjs.github.io/immer/docs/update-patterns), on how to mutate state\n\n## Resources\n\n- [Immer docs](https://immerjs.github.io/immer/)\n- [NgRx docs](https://ngrx.io/docs/)\n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimdeschryver%2Fngrx-immer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimdeschryver%2Fngrx-immer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimdeschryver%2Fngrx-immer/lists"}