--- id: patches title: Patches ---
egghead.io lesson 14: Capture patches using _produceWithPatches_
Hosted on egghead.io
egghead.io lesson 16: Apply Patches using _applyPatches_
Hosted on egghead.io
_⚠ Since version 6 support for Patches has to be enabled explicitly by calling [`enablePatches()`](installation#pick-your-immer-version) once when starting your application._ During the run of a producer, Immer can record all the patches that would replay the changes made by the reducer. This is a very powerful tool if you want to fork your state temporarily and replay the changes to the original. Patches are useful in few scenarios: - To exchange incremental updates with other parties, for example over websockets - For debugging / traces, to see precisely how state is changed over time - As basis for undo/redo or as an approach to replay changes on a slightly different state tree To help with replaying patches, `applyPatches` comes in handy. Here is an example how patches could be used to record the incremental updates and (inverse) apply them: ```javascript import produce, {applyPatches} from "immer" let state = { name: "Micheal", age: 32 } // Let's assume the user is in a wizard, and we don't know whether // his changes should end up in the base state ultimately or not... let fork = state // all the changes the user made in the wizard let changes = [] // the inverse of all the changes made in the wizard let inverseChanges = [] fork = produce( fork, draft => { draft.age = 33 }, // The third argument to produce is a callback to which the patches will be fed (patches, inversePatches) => { changes.push(...patches) inverseChanges.push(...inversePatches) } ) // In the meantime, our original state is replaced, as, for example, // some changes were received from the server state = produce(state, draft => { draft.name = "Michel" }) // When the wizard finishes (successfully) we can replay the changes that were in the fork onto the *new* state! state = applyPatches(state, changes) // state now contains the changes from both code paths! expect(state).toEqual({ name: "Michel", // changed by the server age: 33 // changed by the wizard }) // Finally, even after finishing the wizard, the user might change his mind and undo his changes... state = applyPatches(state, inverseChanges) expect(state).toEqual({ name: "Michel", // Not reverted age: 32 // Reverted }) ``` The generated patches are similar (but not the same) to the [RFC-6902 JSON patch standard](http://tools.ietf.org/html/rfc6902), except that the `path` property is an array, rather than a string. This makes processing patches easier. If you want to normalize to the official specification, `patch.path = patch.path.join("/")` should do the trick. Anyway, this is what a bunch of patches and their inverse could look like: ```json [ { "op": "replace", "path": ["profile"], "value": {"name": "Veria", "age": 5} }, {"op": "remove", "path": ["tags", 3]} ] ``` ```json [ {"op": "replace", "path": ["profile"], "value": {"name": "Noa", "age": 6}}, {"op": "add", "path": ["tags", 3], "value": "kiddo"} ] ``` ### `produceWithPatches`
egghead.io lesson 19: Using inverse patches to build undo functionality
Hosted on egghead.io
egghead.io lesson 20: Use patches to build redo functionality
Hosted on egghead.io
Instead of setting up a patch listener, an easier way to obtain the patches is to use `produceWithPatches`, which has the same signature as `produce`, except that it doesn't return just the next state, but a tuple consisting of `[nextState, patches, inversePatches]`. Like `produce`, `produceWithPatches` supports currying as well. ```javascript import {produceWithPatches} from "immer" const [nextState, patches, inversePatches] = produceWithPatches( { age: 33 }, draft => { draft.age++ } ) ``` Which produces: ```javascript ;[ { age: 34 }, [ { op: "replace", path: ["age"], value: 34 } ], [ { op: "replace", path: ["age"], value: 33 } ] ] ``` For a more in-depth study, see [Distributing patches and rebasing actions using Immer](https://medium.com/@mweststrate/distributing-state-changes-using-snapshots-patches-and-actions-part-2-2f50d8363988) Tip: Check this trick to [compress patches](https://medium.com/@david.b.edelstein/using-immer-to-compress-immer-patches-f382835b6c69) produced over time.