Storybook: How to write story that updates component?

Created on 15 Jul 2016  路  6Comments  路  Source: storybookjs/storybook

I would like to simply see if component behaves correctly when it receives new props. Or even if it receives same props so it's possible to check that there is no logical error with shouldComponentUpdate. Is there some way for that?

Perhaps an idea for addon? Although I see tiny problem with addons that they cannot be combined, so if such functionality comes with addon, I could not use info addon for that story.

discussion

Most helpful comment

componentWillUpdate is not called in the initial render. We always do the initial rendering for all stories. That to prevent to state related issues.

So, if you wanna test componentWillUpdate you need to run render your component inside a wrapper component.

That wrapper component may have a some kind of a button which re-render your original component. Then it'll call the componentWillUpdate.

All 6 comments

Could you explain a bit about this?

Ok simple use case... _(note: ReactStamp can be compared to createClass, nothing special about it here)_

const MyInput = ReactStamp.compose({
    propTypes: {
        externalValue: PT.string
    },
    state: {
        value: ''
    },
    init() {
        this.onChange = (evt) => {
            const { value } = evt.target;
            this.setState({ value });
            // change is also dispatched with delay
        }
    },
    componentWillMount() {
        this.setState({ value: this.props.externalValue });
    },
    componentWillUpdate({ externalValue }) {
        if (externalValue !== this.props.externalValue) {
            this.setState({ value: this.props.externalValue });
        }
    },
    render() {
        return <input value={this.state.value} onChange={this.onChange} />
    }
});

So component is updated on its own with local state as user types and based on debounced input the external value can get updated and should replace what has been typed in the input so far. Think of it as kind of auto completion.

In a story I would like to somehow invoke that componentWillUpdate to see it has been updated properly.

Another more straightforward example...

const Location = ReactStamp.compose({
    propTypes: {
        doUserLocation: PT.func.isRequired,
        userLocation: PT.object,
    },
    componentWillMount() {
        const { userLocation, doUserLocation } = this.props;
        if (userLocation === null) {
            doUserLocation();
        }
    },
    componentWillUpdate(nextProps) {
        if (nextProps.userLocation !== this.props.userLocation) {
            // do something when user location is retrieved
        }
    },
});

Locating user is one time operation so it does happen in mount only. Component will get updated when location is retrieved. I can write story for a first case, but I am failing with other one.

storiesOf('Location', module)
    .addWithInfo('calls doUserLocation when component is mounted',
        `Tries to retrieve user location by IP address.`,
        () => <Location userLocation={null} doUserLocation={action('doUserLocation')} />
    )
    .addWithInfo('calls doLocatePlaces with retrieved user location',
        `This is should be one time operation as user location doesn't change.`,
        () => <Location
            userLocation={userLocation}
            doLocatePlaces={action('doLocatePlaces')}
        />
    )
;

Problem is that my componentWillUpdate never sees the change because that userLocation is within props since the mount.

I've already find out that you are running component updates in a loop, which has helped me to find out about unnecessary updates. However I would like to have some ability to change props for a following update of the component.

componentWillUpdate is not called in the initial render. We always do the initial rendering for all stories. That to prevent to state related issues.

So, if you wanna test componentWillUpdate you need to run render your component inside a wrapper component.

That wrapper component may have a some kind of a button which re-render your original component. Then it'll call the componentWillUpdate.

I think we've a answer for this.

Ah, sorry, I wanted to try it first before responding, but never got a chance with it (more priority stuff). But what you said makes total sense.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miljan-aleksic picture miljan-aleksic  路  3Comments

levithomason picture levithomason  路  3Comments

xogeny picture xogeny  路  3Comments

rpersaud picture rpersaud  路  3Comments

tlrobinson picture tlrobinson  路  3Comments