Skip to content

Instantly share code, notes, and snippets.

@jjrdn
Last active May 12, 2016 00:29
Show Gist options
  • Save jjrdn/0391c0da02e4fa8ce2676bd65439ac10 to your computer and use it in GitHub Desktop.
Save jjrdn/0391c0da02e4fa8ce2676bd65439ac10 to your computer and use it in GitHub Desktop.

It appears that:

  • virtual-hyperscript is creating a new EvHook on each call
  • the diffing algorithm compares the Hooks with reference equality, not the value inside the hook, so they are different every time
  • the result is that all ev-* handlers are patched on every diff

The file explicit.js shows the behaviour I expected, no patch needed. The file hyperscript.js demonstrates the issue, which is this patch:

VirtualPatch {
     type: 4,
     vNode: 
      VirtualNode {
        tagName: 'DIV',
        properties: [Object],
        children: [Object],
        key: undefined,
        namespace: null,
        count: 1,
        hasWidgets: false,
        hasThunks: false,
        hooks: [Object],
        descendantHooks: false },
     patch: { 'ev-click': [Object] } }
//
// This code works as expected
//
const {VNode, VText, diff, create} = require('virtual-dom');
const Delegator = require('dom-delegator');
const EvHook = require('virtual-dom/virtual-hyperscript/hooks/ev-hook');
const onClick = ev => (
console.log('clicked', ev.target)
);
const delegator = Delegator();
delegator.listenTo('click');
const hook = new EvHook(onClick);
// here I explicitly create the vdom, and use the same EvHook every time
const render = () => (
new VNode('DIV', {'ev-click': hook }, [ new VText('text') ])
);
const tree = render();
const tree2 = render();
const p = diff(tree,tree2);
console.log(p);
/* output:
{ a:
VirtualNode {
tagName: 'DIV',
properties: { 'ev-click': [Object] },
children: [ [Object] ],
key: undefined,
namespace: null,
count: 1,
hasWidgets: false,
hasThunks: false,
hooks: { 'ev-click': [Object] },
descendantHooks: false } }
*/
//
// This code demonstrates the issue
//
const {h, diff} = require('virtual-dom');
const Delegator = require('dom-delegator');
const onClick = ev => (
console.log('clicked', ev.target)
);
const delegator = Delegator({defaultEvents: false});
delegator.listenTo('click');
// here I use virtual hyperscript, and use the same function every time
const render = () => h('div', {'ev-click': onClick }, ['text']);
const tree = render();
const tree2 = render();
const p = diff(tree,tree2);
console.log(p);
/* output:
{ '0':
VirtualPatch {
type: 4,
vNode:
VirtualNode {
tagName: 'DIV',
properties: [Object],
children: [Object],
key: undefined,
namespace: null,
count: 1,
hasWidgets: false,
hasThunks: false,
hooks: [Object],
descendantHooks: false },
patch: { 'ev-click': [Object] } },
a:
VirtualNode {
tagName: 'DIV',
properties: { 'ev-click': [Object] },
children: [ [Object] ],
key: undefined,
namespace: null,
count: 1,
hasWidgets: false,
hasThunks: false,
hooks: { 'ev-click': [Object] },
descendantHooks: false } }
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment