Skip to content

Instantly share code, notes, and snippets.

@y-nk
Last active November 13, 2018 07:59
Show Gist options
  • Save y-nk/a22a13c14c93ce76e897a4bff7aa81ec to your computer and use it in GitHub Desktop.
Save y-nk/a22a13c14c93ce76e897a4bff7aa81ec to your computer and use it in GitHub Desktop.
non breaking double binding
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
// ===========================================================================
import deepEqual from 'fast-deep-equal';
import { forceReRender } from '@storybook/react';
import { manager } from '@storybook/addon-knobs/dist/registerKnobs';
// 1. we define a constant which will be unique and used to detect the setter case
const NULL_SYMBOL = Symbol('null')
// 2. we set value to this by default, so when user calls text('label') we can detect it's a getter or not
function text(name, value = NULL_SYMBOL, groupId = null) {
return manager.knob(name, { type: 'text', value, groupId });
}
manager.knob = function(name, options) {
this._mayCallChannel();
const { knobStore } = this;
const existingKnob = knobStore.get(name);
// sorry that i stripped the comments out, but i wanted clarity.
// 3a. we keep this case, and consider it now as a getter for existing knob
if (existingKnob && deepEqual(options.value, existingKnob.defaultValue)) {
return this.getKnobValue(existingKnob);
}
// 3b. in the same fashion, we create this new case which acts as a setter if value parameter is omitted. we check by using our constant
else if (existingKnob && options.value !== NULL_SYMBOL) {
knobStore.set(name, { ...existingKnob, value: options.value })
forceReRender()
return
}
// As there are now 2 returns in the above if statement, this below only belongs to create a new knob.
// To make sure that there will be no complication if user calls text('newlabel') for the first time,
// we use this ternary to secure 'value' and 'defaultValue'
const value = options.value !== NULL_SYMBOL ? options.value : '';
const defaultValue = value;
const knobInfo = {
...options,
name,
value,
defaultValue,
};
knobStore.set(name, knobInfo);
return this.getKnobValue(knobStore.get(name));
}
// ============================================================================
const stories = storiesOf('Knobs demo', module)
stories.addDecorator(withKnobs)
stories.add('input text', () => (
<input type="text" value={ text('value', 'default value') } onChange={ e => text('value', e.target.value) } />
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment