Search code examples
reactjsstaterenderingreact-props

React is not re-rendering on state change


I am receiving data from props and I have to wait until I receive it so that I can slice it. Meanwhile, I want to show a circular progress bar while it is loading until loading state is set to false and it rerenders.

However, right now it is stuck on loading and componentWillReceiveProps() does not trigger unless I manually refresh the page? Why?

import React, { Component } from "react";
import { connect } from "react-redux";
import MemberSync from "./MemberSync";
import CircularProgress from "@material-ui/core/CircularProgress";

interface IProps {
  orgUsers: object;
}
interface IState {
  loading: boolean;
}

class MemberSyncContainer extends Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      loading: true,
    };
  }

  componentWillReceiveProps() {
    this.setState({ loading: false });
  }

  render() {
    let orgUsers = this.props.orgUsers;
    if (this.state.loading) return <CircularProgress />;
    let usersArray = Object.values(orgUsers).slice(0, -1);
    return <MemberSync usersArray={usersArray} />;
  }
}

const mapStateToProps = (state: any) => {
  return {
    orgUsers: state.orgusers,
  };
};
export default connect(mapStateToProps)(MemberSyncContainer);

Solution

  • You should avoid componentWillReceiveProps. It has been set as unsafe and they say it often results in bugs and inconsitencies.
    See https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops

    You should probably do a check if the props has changed using componentDidUpdate instead. This should probably do the trick.

    componentDidUpdate(prevProps) {
      if (this.props !== prevProps) {
        this.setState({ loading: false });
      }
    }
    

    You can see more at https://reactjs.org/docs/react-component.html#componentdidupdate