Last active
November 21, 2020 18:39
-
-
Save kenwebb/48aa9e2a6d15b79dd33f21757fcb3659 to your computer and use it in GitHub Desktop.
immer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Sat Nov 21 2020 13:39:15 GMT-0500 (Eastern Standard Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: immer | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 48aa9e2a6d15b79dd33f21757fcb3659 | |
Keywords: | |
My Notes | |
-------- | |
October 30, 2020 | |
This workbook explores immer and similar projects and ideas. | |
I should be able to use in with Xholon, React | |
http://127.0.0.1:8080/war/Xholon.html?app=immer&src=lstr&gui=clsc&jslib=immer | |
To install and test | |
------------------- | |
cd ~/nodespace/ OR cd ~/nodespace/node_modules ??? | |
npm install immer | |
cd immer | |
ls -al | |
I should be able to use either of the following in Xholon (with size in bytes): | |
NO immer.cjs.development.js 57653 | |
NO immer.cjs.production.min.js 15338 | |
These files are in the dist directory. | |
I copied immer.cjs.development.js to Xholon public/lib/immer.js | |
I need to use the following files instead: | |
immer.umd.development.js 59545 | |
immer.umd.production.min.js 15390 | |
Simple Example [ref 6] | |
-------------- | |
import produce from "immer" | |
const baseState = [ | |
{ | |
todo: "Learn typescript", | |
done: true | |
}, | |
{ | |
todo: "Try immer", | |
done: false | |
} | |
] | |
const nextState = produce(baseState, draftState => { | |
draftState.push({todo: "Tweet about it"}) | |
draftState[1].done = true | |
}) | |
Running this example in Firefox Dev Tools (it works) | |
-------------------- | |
const baseState = [ | |
{ | |
todo: "Learn typescript", | |
done: true | |
}, | |
{ | |
todo: "Try immer", | |
done: false | |
} | |
] | |
console.log(baseState); | |
const nextState = immer.produce(baseState, draftState => { | |
draftState.push({todo: "Tweet about it"}) | |
draftState[1].done = true | |
}) | |
console.log(nextState); | |
References | |
---------- | |
(1) https://github.com/immerjs/immer | |
Create the next immutable state tree by simply modifying the current tree | |
Winner of the "Breakthrough of the year" React open source award and "Most impactful contribution" JavaScript open source award in 2019 | |
JavaScript, TypeScript | |
Michel Westrate | |
(2) https://www.npmjs.com/package/immer | |
(3) https://immerjs.github.io/immer/docs/introduction | |
Immer (German for: always) is a tiny package that allows you to work with immutable state in a more convenient way. | |
It is based on the copy-on-write mechanism. | |
The basic idea is that you will apply all your changes to a temporary draftState, which is a proxy of the currentState. | |
Once all your mutations are completed, Immer will produce the nextState based on the mutations to the draft state. | |
This means that you can interact with your data by simply modifying it while keeping all the benefits of immutable data. | |
(4) https://immerjs.github.io/immer/docs/installation | |
Immer can be installed as a direct dependency, and will work in any ES5 environment | |
Yarn: yarn add immer | |
NPM: npm install immer | |
CDN: Exposed global is immer | |
Unpkg: <script src="https://unpkg.com/immer"></script> | |
JSDelivr: <script src="https://cdn.jsdelivr.net/npm/immer"></script> | |
see additional details on this page | |
(5) https://github.com/immerjs/use-immer | |
A hook to use immer as a React hook to manipulate state. | |
(6) https://immerjs.github.io/immer/docs/patches | |
The generated patches are similar (but not the same) to the RFC-6902 JSON patch standard, | |
KSW this may be what I use with Xholon Meteor | |
(7) https://immerjs.github.io/immer/docs/produce | |
basic example | |
(8) https://medium.com/hackernoon/introducing-immer-immutability-the-easy-way-9d73d8f71cb3 | |
How does Immer work? | |
Well, two words; 1) Copy-on-write. 2). Proxies. Let me draw a picture. | |
immer uses structural sharing | |
(9) https://en.wikipedia.org/wiki/Copy-on-write | |
(10) https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Proxy | |
The Proxy object enables you to create a proxy for another object, which can intercept and redefine fundamental operations for that object. | |
(11) https://egghead.io/courses/immutable-javascript-data-structures-with-immer | |
Immutable JavaScript Data Structures with Immer | |
58m | |
I did not watch this. They require creating an account. | |
(12) https://github.com/jherr/react-drops | |
) https://www.youtube.com/watch?v=7XeX5SPKicQ | |
Port of Hue Drops into React using immer | |
a game, TypeScript | |
looks like a good example | |
(13) https://osawards.com/react/ | |
OS Awards | |
(14) https://github.com/mariocasciaro/object-path-immutable | |
) https://www.npmjs.com/package/object-path-immutable | |
object-path-immutable | |
Tiny JS library to modify deep object properties without modifying the original object (immutability). | |
Works great with React (especially when using setState()) and Redux (inside a reducer). | |
This can be seen as a simpler and more intuitive alternative to the React Immutability Helpers and Immutable.js. | |
Quick usage | |
The following, sets a property without modifying the original object. | |
It will minimize the number of clones down the line. | |
The resulting object is just a plain JS object literal, so be warned that it will not be protected against property mutations (like Immutable.js) | |
const obj = { | |
a: { | |
b: 'c', | |
c: ['d', 'f'] | |
} | |
} | |
const newObj = immutable.set(obj, 'a.b', 'f') | |
// { | |
// a: { | |
// b: 'f', | |
// c: ['d', 'f'] | |
// } | |
// } | |
// obj !== newObj | |
// obj.a !== newObj.a | |
// obj.a.b !== newObj.a.b | |
// However: | |
// obj.a.c === newObj.a.c | |
(15) TODO | |
]]></Notes> | |
<_-.XholonClass> | |
<PhysicalSystem/> | |
<Block/> | |
<Brick/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
</xholonClassDetails> | |
<PhysicalSystem> | |
<Block/> | |
</PhysicalSystem> | |
<Blockbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
// ======================================================================== | |
// this works! | |
const baseState = [ | |
{ | |
todo: "Learn typescript", | |
done: true | |
}, | |
{ | |
todo: "Try immer", | |
done: false | |
} | |
] | |
console.log(baseState); | |
$wnd.xh.root().println(JSON.stringify(baseState)); | |
const nextState = $wnd.immer.produce(baseState, draftState => { | |
draftState.push({todo: "Tweet about it"}) | |
draftState[1].done = true | |
}) | |
console.log(nextState); | |
$wnd.xh.root().println(JSON.stringify(nextState)); | |
// ======================================================================== | |
// try it with a Xholon node this partly works | |
// TODO it creates the new node, which refs everything just like the original base node, but it's NOT part of the Xholon tree | |
console.log(this); | |
const xhbaseState = $wnd.xh.root().first().first(); | |
xhbaseState[$wnd.immer.immerable] = true | |
console.log(xhbaseState); | |
xhbaseState.println(xhbaseState); | |
const xhnextState = $wnd.immer.produce(xhbaseState, xhdraftState => { | |
xhdraftState["testing"] = 123 | |
}) | |
console.log(xhnextState); | |
xhnextState.println(xhnextState); | |
// FIXED Uncaught Error: [Immer] produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got 'block_46' | |
//# sourceURL=Blockbehavior.js | |
]]></Blockbehavior> | |
<Heightbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
var myHeight, testing; | |
var beh = { | |
postConfigure: function() { | |
testing = Math.floor(Math.random() * 10); | |
myHeight = this.cnode.parent(); | |
}, | |
act: function() { | |
myHeight.println(this.toString()); | |
}, | |
toString: function() { | |
return "testing:" + testing; | |
} | |
} | |
//# sourceURL=Heightbehavior.js | |
]]></Heightbehavior> | |
<Brickbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
$wnd.xh.Brickbehavior = function Brickbehavior() {} | |
$wnd.xh.Brickbehavior.prototype.postConfigure = function() { | |
this.brick = this.cnode.parent(); | |
this.iam = " red brick"; | |
}; | |
$wnd.xh.Brickbehavior.prototype.act = function() { | |
this.brick.println("I am a" + this.iam); | |
}; | |
//# sourceURL=Brickbehavior.js | |
]]></Brickbehavior> | |
<Brickbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
console.log("I'm another brick behavior"); | |
]]></Brickbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Block</title> | |
<rect id="PhysicalSystem/Block" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
<g> | |
<title>Height</title> | |
<rect id="PhysicalSystem/Block/Height" fill="#6AB06A" height="50" width="10" x="80" y="0"/> | |
</g> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment