Reputation: 595
I have the following state
variable and componentDidMount
method on my component:
state = {
categorized_items: []
}
componentDidMount() {
this.props.fetchItems()
// I'm trying to do the following
console.log('uncat_items: ', this.props.uncat_items)
this.setState({categorized_items: this.props.uncat_items})
}
render () {....}
function mapStateToProps({ items_reducer }) {
return {
uncat_items: items_reducer.uncat_items
}
}
The this.props.fetchItems()
action method fetches a number of items and updates the uncat_items
in the redux store just fine (I can see the expected values for the this.props.uncat_items
variable in the render/other methods without any problem). However, what I need to do for this particular case is right after the fetchItems
method is executed and it updates the uncat_items
in the store, I need to call setState
and update the categorized_items
in the state with uncat_items
. I know calling this.setState
like this in the componentDidMount
method is not correct, but I don't know how to do that. As you can see I tried printing out this.props.uncat_items
, but that returns an empty array, even though it executed the action method and updated in the reducer properly. Can someone please give me an idea how to do it the right way? Basically, after componentDidMount
executes, set the state with a particular variable from the updated redux store.
Upvotes: 0
Views: 464
Reputation: 526
You can use the componentDidUpdate lifecycle method. It looks like when your component is mounting your store might still contain the default value for that piece of state. It then updates correctly in the redux store as you mentioned but the component state is not updated.
To update component state after new props are received by the component:
componentDidUpdate(prevProps){
// compare prevProps to current props and update
if(this.props.uncat_items !== prevProps.uncat_items) {
this.setState({categorized_items: this.props.uncat_items})
}
}
As mentioned in comments, using props directly in the render method is the more ideal solution as you don’t want your component to needlessly re-render.
Upvotes: 1
Reputation: 314
The problem in your code is that you invoke an asynchronous action (this.props.fetchItems()
) and then immediately invoke this.setState()
- which happens before the fetchItems
request finishes (thus, before props.uncat_items
gets populated).
Assuming you are using newest React, depending on your particular use case, you can either:
1) Drop state and just use directly this.props.uncat_items
in the render function.
2) Use static getDerivedStateFromProps
to update state due to new props.
However, as mentioned in the docs, it's not really recommended, as most cases can be handled differently (e.g. by switching to a controlled component, as stated in solution #1). A longer description can be found in this article, which is also mentioned in the docs.
Upvotes: 2