0
votes

I want to set the local state of a component using props obtained from mapStateToProps. When I use this.setState in ComponentWillMount() method or ComponentDidMount() method, it is undefined.

componentWillMount() {
    this.props.fetchBooks(this.props.id);
    this.setState({
      books:this.props.books
    })
  }
const mapStateToProps = (state, ownProps) => {
  let id = ownProps.match.params.book_id;
  return {
    id: id,
    books: state.library.books,
  };
};

The 'books' data is retrieved using the fetchBooks() function obtained by mapDispatchToProps. How can I set the sate using the props obtained from mapStateToProps?

3
Do not use componentWillMount this method is deprecated and will be removed soon thus breaking your application if you update your React version. If you must have this in a lifecycle hook, I suggest verifying the props in shouldComponentUpdate or componentDidUpdate methods.Baruch
What does this.props.fetchBooks(this.props.id); do? Is it a thunk action fetching books? When you fetch the books the component continues rendering but the books are not there yet, maybe in the thunk action dispatch loading, ok or error actions so you can get these values from redux state.HMR

3 Answers

1
votes

The problem might be that this.props.fetchBooks is an asynchronous operation. In that case, this.setState is called before the operation is completed, hence the undefined value.

But why do you want to store the books in the local state? Why don't you use directly the books prop instead?

Using derived state is usually unnecessary, and might be a bad idea (see this blog post from the official React website for an in-depth explanation).

If you really need to store the books in the local state, you could:

0
votes

Your componentWillMount lifecycle method will only fire once, so using it to call the function that fetches the data and also use the data will most likely not work. You should use componentWillReceiveProps instead.

constructor(props) {
    props.fetchBooks(props.id);
}

componentWillReceiveProps(nextProps) {
    if (nextProps.books != this.props.books) {
        this.setState({books: nextProps.books});
    }
}
0
votes

You better use straight inside your render() {} this.props.assignedSupervisors instead of putting it in a class state.

Otherwise use

componentDidUpdate(prevProps, prevState) {
 if (this.props.assignedSupervisors && this.props.assignedSupervisors !== prevProps.assignedSupervisors) {
  this.setState({
     supervisors:this.props.assignedSupervisors
  })
 }
}