Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding WithState and withState helpers to allow pure components actually change their state in stories #78

Closed
wants to merge 15 commits into from

Conversation

ilyabo
Copy link

@ilyabo ilyabo commented Apr 7, 2016

WithState or withState can be used to wrap a component and inject into it prop values coming from change handlers:

import { storiesOf, action, withState, WithState } from '@kadira/storybook'

storiesOf('ui.ButtonGroup', module)

  .add('segmented control', () =>
      <WithState handlers={{ onButtonSelected: 'activeId' }}>
          <ButtonGroup type="segmentedControl"
                       activeId={ 1 }
                       items={ [ { id: 1, name: 'One' }, { id: 2, name: 'Two' } ] }
                       onButtonSelected={ action('onButtonSelected') }
                    />
      </WithState>  
  )

  .add('tabbed pane', withState({ onButtonSelected: 'activeId' }, () =>
     <ButtonGroup type="tabbedPane"
                  activeId={ 1 }
                  items={ [ { id: 1, name: 'One' }, { id: 2, name: 'Two' } ] }
                  onButtonSelected={ action('onButtonSelected') }
                />
  ))

@arunoda
Copy link
Member

arunoda commented Apr 7, 2016

Could you give us more information about this PR, may be a complete use case?

And I really like to have a single API to do a thing. So, I think just having withState is good enough.

@ilyabo
Copy link
Author

ilyabo commented Apr 8, 2016

In plain stories you can't see state changes in pure components. WithState is a simple way to add a state container to a component and see it in action as it would look like in a real app:
react-storybook-withstate

If I had to keep only one of the two API variants, I would keep the component WithState then, because the function it is more difficult to use if you want to wrap your component in something else, e.g.:

.add('with WithState', () =>

    <div style={{ width: 200 }}>
      <WithState handlers={{ onButtonSelected: 'activeId' }}>


          <ButtonGroup type="segmentedControl"
                       activeId={ 1 }
                       items={ [ { id: 1, name: 'One' }, { id: 2, name: 'Two' } ] }
                       onButtonSelected={ action('onButtonSelected') }
                    />


      </WithState>
    </div>

  )

@jeef3
Copy link
Contributor

jeef3 commented Apr 11, 2016

It looks like the WithState is intercepting the specified props (onButtonSelected) and updating the paired property (activeId) based on the args that the onButtonSelected func passes.

It looks like it the idea is similar to linkTo functionality, but without changing the story. Instead, it applies the new prop values and re-renders the component (via a setState call within the WithState component).

If you go down the path of providing a way to update the props of a component within a story, then you also be able to open up a way of allowing those props to be a bit more dynamically updated. For example, potentially updated via a text box in the UI.

I wonder if the API could be a bit more generic by accepting functions rather than just strings?

<WithState handlers={onButtonSelected: props => activeId => ({ ...props, { activeId }})}>

// Which looks a little crazy, but is basically:

function onButtonSelected(props) { // WithState passes in the props
  return function (activeId) { // Your component passes in arbitrary args
    return Object.assign(
      {},
      props,
      { activeId: activeId }
    );
  }
}

// So, given a props object, return a new one with the expected state.

Which might make more sense with some name changes (lots of code emitted):

<PropsContainer updaters={onButtonSelected: /* as above */}>
  {props => (
    <ButtonGroup
        activeId={props.activeId}
        onButtonSelected={props.onButtonSelected} />
  )}
</PropsContainer>

Sorry for the ramble, just spitballing here

@ilyabo
Copy link
Author

ilyabo commented Apr 12, 2016

👍 thanks for the interesting suggestion @jeef3! I also thought about adding support for functions in handlers, but it didn't bring me that far :) let's see what @arunoda thinks about it.

@ritz078
Copy link
Contributor

ritz078 commented Apr 19, 2016

@ilyabo any update on this ? Needed it for a project. that's why I'm asking.

@arunoda
Copy link
Member

arunoda commented Apr 19, 2016

@ilyabo I think this is great and this doesn't need any support from core storybook APIs. So, I think it's better to create this as a independent NPM module.

We can have a link in the README to addons and list this project there.

@arunoda
Copy link
Member

arunoda commented May 9, 2016

I'm going to close this in-favour of separate NPM as mentioned in the above comment.

@arunoda arunoda closed this May 9, 2016
ndelangen pushed a commit that referenced this pull request Apr 5, 2017
ndelangen pushed a commit that referenced this pull request Apr 5, 2017
@shilman shilman added the misc label May 27, 2017
ndelangen pushed a commit that referenced this pull request Feb 23, 2024
Copy link

nx-cloud bot commented Jun 12, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit f37f279. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 1 target

Sent with 💌 from NxCloud.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants