Skip to content

Instantly share code, notes, and snippets.

@alexanderson1993
Created August 1, 2020 12:01
Show Gist options
  • Save alexanderson1993/f478d50e58761f20f63f59dc15882f0c to your computer and use it in GitHub Desktop.
Save alexanderson1993/f478d50e58761f20f63f59dc15882f0c to your computer and use it in GitHub Desktop.
Apply immer patches loosely to an object, in case the object doesn't match the object which the patches were created against in the first place.
import { produce, applyPatches, enablePatches } from "immer";
enablePatches();
function setToValue(obj, value, path) {
var i;
path = path.split(".");
for (i = 0; i < path.length - 1; i++) {
if (!obj[path[i]]) {
obj[path[i]] = isNaN(parseInt(path[i], 10)) ? {} : [];
}
obj = obj[path[i]];
}
obj[path[i]] = value;
}
function looseApplyPatches(startingState, patches) {
try {
return applyPatches(startingState, patches);
} catch (err) {
if (err.message.includes("Cannot apply patch, path doesn't resolve: ")) {
const path = err.message.split(": ")[1];
const objPath = path.split("/").join(".");
const newStartingState = { ...startingState };
setToValue(newStartingState, undefined, objPath);
return looseApplyPatches(newStartingState, patches);
}
throw err
}
}
@alexanderson1993
Copy link
Author

Usage:

const data = { a: { c: 4, d: 5, e: [1, 2, 3] }, b: 2 };
let patchList;

const newData = produce(
  data,
  draft => {
    draft.a.c = 6;
    draft.a.e.push("6");
    draft.b = true;
    draft.c = "awesome";
  },
  patches => {
    patchList.push(patches);
  }
);

const missingData = { b: 2 };
const newState = looseApplyPatches(missingData, patchList);
console.log(newState)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment