Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active November 21, 2020 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/48aa9e2a6d15b79dd33f21757fcb3659 to your computer and use it in GitHub Desktop.
Save kenwebb/48aa9e2a6d15b79dd33f21757fcb3659 to your computer and use it in GitHub Desktop.
immer
<?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