Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import produce, { current } from "immer";
type Node = {
value: string;
children: Node[];
};
const tree: Node = {
value: "root",
children: [
{
value: "a",
children: [],
},
{
value: "b",
children: [],
},
],
};
// meta
type TouchedNode = Node & { [key: string]: string };
type IndexedRoot = {
root: TouchedNode;
indexer: { [key: string]: any };
};
let n = 1;
const uniqueId = () => (n++).toString();
function createIndex(root: Node): IndexedRoot {
const indexer: { [key: string]: any } = {};
function walk(node: Node) {
const id = uniqueId();
(node as TouchedNode).__id__ = id;
// @ts-ignore
const ref = new WeakRef(node);
indexer[id] = ref;
node.children.forEach(walk);
}
walk(root);
return {
root: root as TouchedNode,
indexer,
};
}
const indexed: IndexedRoot = createIndex(tree);
const newData = produce(indexed, (draft: IndexedRoot) => {
const ref = draft.indexer["3"]; // change b
const target = ref.deref();
target.value = "b-touched";
});
console.log("original", indexed);
console.log("touched", newData);
/* Result
original {
root: {
value: "root",
children: [
{ value: "a", children: [Array], __id__: "2" },
{ value: "b-touched", children: [Array], __id__: "3" }
],
__id__: "1"
},
indexer: { "1": WeakRef {}, "2": WeakRef {}, "3": WeakRef {} }
}
touched {
root: {
value: "root",
children: [
{ value: "a", children: [Array], __id__: "2" },
{ value: "b-touched", children: [Array], __id__: "3" }
],
__id__: "1"
},
indexer: { "1": WeakRef {}, "2": WeakRef {}, "3": WeakRef {} }
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment