Kevin Lee
Kevin Lee

Reputation: 1191

Should I call actions within componentWillReceiveProps?

My instinct tells me no, but I'm having difficultly thinking of a better way.

Currently, I have a component that displays a list of items. Depending on the provided props, this list may change (i.e. filtering change or contextual change)

For example, given a new this.props.type, the state will be updated as follows:

componentWillReceiveProps(nextProps) {
        if (nextProps.type == this.state.filters.type) return

        this.setState({
            filters: {
                ...this.state.filters,
                type: nextProps.type,
            },
            items: ItemsStore.getItems().filter(item => item.type == nextProps.type)
        })
}

This is all fine and good, but now my requirements have changed and I need to add a new filter. For the new filter, I must execute an API call to return a list of valid item ids and I only want to display items with these ids in the same list component. How should I go about this?

I had thought about calling the appropriate action from componentWillReceiveProps, but that doesn't seem right.

componentWillReceiveProps(nextProps) {
        if (nextProps.type == this.state.filters.type && nextProps.otherFilter == this.state.filters.otherFilter) return

        if (nextProps.otherFilter != this.state.filters.otherFilter) {
            ItemsActions.getValidIdsForOtherFilter(nextProps.otherFilter)
            // items will be properly updated in store change listener, onStoreChange below
        }

        this.setState({
            filters: {
                ...this.state.filters,
                type: nextProps.type,
                otherFilter: nextProps.otherFilter,
            },
            items: ItemsStore.getItems().filter(item => item.type == nextProps.type)
        })
},

onStoreChange() {
     let validIds = ItemsStore.getValidIds()

     this.setState({
         items: ItemsStore.getItems().filter(item => item.type == this.state.filters.type && validIds.indexOf(item.id) > -1)
     })
}

Upvotes: 3

Views: 4567

Answers (1)

amann
amann

Reputation: 5902

Update 22nd January 2018:

Recently an RFC-PR for React was merged, which deprecates componentWillReceiveProps as it can be unsave when used in the upcoming async rendering mode. An example for this can be calling flux actions from this lifecycle hook.

The correct place to call actions (i.e. side effects) is after React is done rendering, so that means either componentDidMount or componentDidUpdate.

If the intention of the action is to fetch data, React might support a new strategy for these things in the future. In the meantime it's safe to stick to the two mentioned lifecycle hooks.

Upvotes: 10

Related Questions