{"id":7376,"date":"2019-08-29T21:15:18","date_gmt":"2019-08-29T21:15:18","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7376"},"modified":"2019-08-29T21:15:18","modified_gmt":"2019-08-29T21:15:18","slug":"storybook-and-state-also-uses-sambego-storybook-state","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/storybook-and-state-also-uses-sambego-storybook-state\/","title":{"rendered":"Storybook and state (also uses @sambego\/storybook-state)"},"content":{"rendered":"<p>There&#8217;s several ways to setup your components for testing within Storybook to allow us to change our component&#8217;s properties &#8211; using Knobs or creating wrapper components to encompass state changes through to hooking up to a redux store.<\/p>\n<p>Let&#8217;s look at an example of wrapping our component within a story. <\/p>\n<p>So I have an AppBar within a selection component. I want to see the story maintain the state changes when the user changes the selection. Now, no actual state is stored within the component itself as it&#8217;s passed up the component hierarchy to a parent component and\/or redux store. This means, without setting up a parent component or redux store the selection changes but the actual value on the component remains the same.<\/p>\n<p>One way to achieve this is to create a wrapper parent component, i.e. a minimal wrapper component around our component under test, for example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass WrapperComponent extends React.Component&lt;any, any&gt; {\r\n  constructor(props) {\r\n    super(props);\r\n\r\n    this.state = { ...props }\r\n  }\r\n\r\n  render() {\r\n    const props = { \r\n      ...this.props,\r\n      onSelectionChanged: (selected, _) =&gt; this.setState({selected: selected}),\r\n      selected: this.state.selected\r\n    }\r\n\r\n    return &lt;ComponentUnderTest {...props} \/&gt;\r\n  }\r\n}\r\n<\/pre>\n<p>So as you can see, the ComponentUnderTest is wrapped in a WrapperComponent and hooked up to props along with state changes, now we simply have the story return the WrapperComponent, i.e.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nconst props = {\r\n  selected: 'None'\r\n}\r\n\r\nreturn &lt;WrapperComponent {...props}\/&gt;\r\n<\/pre>\n<p>Easy enough and could be rewritten to make it more generic, but there&#8217;s an alternative and that&#8217;s to use something like <a href=\"https:\/\/github.com\/Sambego\/storybook-state\" rel=\"noopener noreferrer\" target=\"_blank\">@sambego\/storybook-state<\/a><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyarn add -D @sambego\/storybook-state\r\n<\/pre>\n<p>In which case we can write our story like this instead<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { Store, State } from &quot;@sambego\/storybook-state&quot;;\r\n\r\nconst storeState = new Store({\r\n  selectedPublicQuery: &quot;None&quot;\r\n});\r\n\r\nstoriesOf(&quot;ComponentUnderTest&quot;, module)\r\n  .add(&quot;default&quot;, () =&gt; {\r\n    return (\r\n      &lt;State store={storeState}&gt;\r\n        {state =&gt; \r\n          &lt;ComponentUnderTest selected={state.selected} \r\n              onSelectionChanged={(selected, _) =&gt; storeState.set({selected: selected})}\/&gt;\r\n          }\r\n        &lt;\/State&gt;\r\n      );\r\n  });\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>There&#8217;s several ways to setup your components for testing within Storybook to allow us to change our component&#8217;s properties &#8211; using Knobs or creating wrapper components to encompass state changes through to hooking up to a redux store. Let&#8217;s look at an example of wrapping our component within a story. So I have an AppBar [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[243,251],"tags":[],"class_list":["post-7376","post","type-post","status-publish","format-standard","hentry","category-react","category-storybook"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7376"}],"version-history":[{"count":2,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7376\/revisions"}],"predecessor-version":[{"id":7380,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7376\/revisions\/7380"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}