Reputation: 3276
Storybook recommends technique for making a copy of a function:
const Template = args => <Task {...args} />;
export const Default = Template.bind({});
It allows each exported story to set its own properties, but use the same implementation.
I understand result but don't get why it has to bind function to an empty object {}
Upvotes: 2
Views: 490
Reputation: 7086
The above code snippet is using bind()
on an arrow function:
const Template = args => <Task {...args} />;
export const Default = Template.bind({});
Using bind
on an arrow function does not modify the behavior of the arrow function at all, since the this
of an arrow function will always be the scope where the arrow function was defined.
MDN recommends not to use bind
on arrow functions MDN - Arrow function expressions: call, apply and bind
The call, apply and bind methods are NOT suitable for Arrow functions -- as they were designed to allow methods to execute within different scopes -- because Arrow functions establish "this" based on the scope the Arrow function is defined within.
const arrowFn = () => {
console.log('this.foo:', this.foo);
};
window.foo = 'window.foo';
const myObj = {
foo: 'myObj.foo'
};
const boundFn = arrowFn.bind(myObj);
arrowFn(); // 'window.foo'
boundFn(); // 'window.foo'
Since bind
can't modify an arrow function, the only useful thing bind
is doing in this example above is creating a new wrapper function that can have its own unique properties.
Therefore, the code from the supplied example:
const Template = (...args) => {};
const Default = Template.bind({});
Default.args = {...};
could be replaced with:
const Template = (...args) => {};
Default = function () { Template(...arguments); }
Default.args = {...};
This second pattern has the advantage of not using bind
in a non-standard way.
Upvotes: 1
Reputation: 3080
The full relevant code from the link you provided is:
import React from 'react';
import Task from './Task';
export default {
component: Task,
title: 'Task',
};
const Template = args => <Task {...args} />;
export const Default = Template.bind({});
Default.args = {
task: {
id: '1',
title: 'Test Task',
state: 'TASK_INBOX',
updatedAt: new Date(2018, 0, 1, 9, 0),
},
};
export const Pinned = Template.bind({});
Pinned.args = {
task: {
...Default.args.task,
state: 'TASK_PINNED',
},
};
Using Template.bind({})
allows for the extra members, such as Default.args = {...}
, to be defined differently on each copy and from the original (not used here).
As already said in the docs from the link:
Template.bind({})
is a standard JavaScript technique for making a copy of a function. We use this technique to allow each exported story to set its own properties, but use the same implementation.
Upvotes: 2