Compressing patches #1976
-
Is there a way to compress MST patches like in immer? https://medium.com/@dedels/using-immer-to-compress-immer-patches-f382835b6c69 I am handling patches in between snapshots, but noticing that an add followed by a replace operation is not compressed into a singular add, which would be useful so I would only have to handle a single path once. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hi @BrianHung! I just ported that Immer example to MST, and I don't think that is supported. I can't say for certain that it's unachievable, but I don't think it is right now. import { applyPatch, applySnapshot, onPatch, types } from "mobx-state-tree";
const Model = types
.model({
a: 1,
b: types.maybe(types.number)
})
.actions((self) => ({
setA(a: number) {
self.a = a;
},
setB(b: number) {
self.b = b;
},
reset() {
applySnapshot(self, {});
}
}));
const patches: any = [];
const compiledPatches: any = [];
const model = Model.create();
const dispose = onPatch(model, (patch) => patches.push(patch));
model.setB(9);
model.setA(3);
model.setB(99);
model.setA(5);
console.log(patches);
// (4) [Object, Object, Object, Object]
dispose();
model.reset();
onPatch(model, (patch) => compiledPatches.push(patch));
applyPatch(model, patches);
console.log(compiledPatches);
// (4) [Object, Object, Object, Object] |
Beta Was this translation helpful? Give feedback.
-
There are two ways of compressing patches.
import { applyPatches, enablePatches, Patch, produceWithPatches } from "immer";
import { joinJsonPath, splitJsonPath, type IJsonPatch, isStateTreeNode, getSnapshot } from "mobx-state-tree";
export const getImmerPatch = ({ path, ...patch }: IJsonPatch) => ({ path: splitJsonPath(path), ...patch });
export const getMSTPatch = ({ path, ...patch }: Patch) => ({ path: joinJsonPath(path as string[]), ...patch });
/**
* Compresses JsonPatches using immer. Requires snapshot of previous state.
* https://medium.com/@dedels/using-immer-to-compress-immer-patches-f382835b6c69
* @param prevState
* @param patches
* @returns
*/
export function compressImmerPatches(prevState: IEditorState, patches: Patch[]) {
const snapshot = isStateTreeNode(prevState) ? getSnapshot(prevState) : prevState;
const [next, compressed, inverse] = produceWithPatches<IEditorState>(snapshot, draft => applyPatches(draft, patches));
return compressed;
}
const patches = []
onPatch(state, patch => patches.push(patch))
const lastSnapshot = state.toJSON();
onSnapshot(state, snapshot => {
const compressed compressImmerPatches(lastSnapshot, patches.map(getImmerPatch)).map(getMSTPatch)
lastSnapshot = snapshot
})
/**
* Compresses JsonPatches using a Radix Trie.
* @param patches
* @returns
*/
export function compressPatches(patches: Patch[]) {
const trie = new PatchRadixTrie(patches);
return trie.getPatches();
}
const patches = []
onPatch(state, patch => patches.push(patch))
const compressed = compressPatches(patches.map(getImmerPatch)).map(getMSTPatch); |
Beta Was this translation helpful? Give feedback.
Hi @BrianHung!
I just ported that Immer example to MST, and I don't think that is supported. I can't say for certain that it's unachievable, but I don't think it is right now.