title: setState within componentDidUpdate comparing prev with current state not working to re-render page with new data, also getting infinite loop
body: <p>I am relatively beginner in React, and in this particular situation, I am probably missing something very fundamental.</p>
  
  <p>Here, I have a simple CRUD app, and after user adds new data, the updated list of items should be rendered. And the new data is added with a second Dialog component <strong>AddNewDevelopmentWork.js</strong></p>
  
  <p>So, after new data is added by the <strong>AddNewDevelopmentWork.js</strong> (which is the child compoenent that will only open a dialog for the user to input and fill few TestFields),  in the main component (<strong>DevelopmentList.js</strong>), I am using <strong>componentDidUpdate</strong> to do the comparison with current state and prevState (for the state variable <strong>allDevelopmentWorks</strong> which is an array of objects) , and if they are not equal then make a request to the backend Express API and fetchin data and updating state within <strong>componentDidUpdate</strong>. And then render with new data.</p>
  
  <p>Problem is, this main <strong>DevelopmentList.js</strong> component is not rendering the new data entered by the user till the page is refreshed. But after refreshing the page manually its showing the newly entered data.</p>
  
  <p>Here is my <strong>DevelopmentList</strong> component. </p>
  
  <pre><code> class DevelopmentList extends Component {
        constructor(props) {
          super(props);
          this.state = {
            allDevelopmentWorks: []
          };
        }
  
      componentDidUpdate(prevProps, prevState) {
          if (
            this.state.allDevelopmentWorks.length !==
            prevState.allDevelopmentWorks.length
          ) {
            return axios
              .get("/api/developmenties")
              .then(res =&gt; {
                this.setState({
                  allDevelopmentWorks: res.data
                });                  
              })
              .catch(function(error) {
                console.log(error);
              });
          }
        }
  
        componentDidMount() {
          axios.get("/api/developmenties").then(res =&gt; {
            this.setState({
              allDevelopmentWorks: res.data
            });
          });
        }
  
      render() {
  const { classes } = this.props;
  return (
    &lt;div&gt;
      &lt;Table className={classes.table}&gt;
        &lt;TableHead&gt;
          &lt;TableRow className={classes.row}&gt;
            &lt;CustomTableCell align="left"&gt;Location&lt;/CustomTableCell&gt;
            &lt;CustomTableCell align="left"&gt;
              Description Of Work
            &lt;/CustomTableCell&gt;
            &lt;CustomTableCell align="left"&gt;
              Date of Commencement
            &lt;/CustomTableCell&gt;
            &lt;CustomTableCell align="left"&gt;Date of Completion&lt;/CustomTableCell&gt;
            &lt;CustomTableCell align="left"&gt;Status of Work&lt;/CustomTableCell&gt;
          &lt;/TableRow&gt;
        &lt;/TableHead&gt;
        &lt;TableBody&gt;
          {this.state.allDevelopmentWorks.map((document, i) =&gt; (
            &lt;TableRow className={classes.row} key={i}&gt;
              &lt;CustomTableCell component="th" scope="row"&gt;
                {document.location}
              &lt;/CustomTableCell&gt;
              &lt;CustomTableCell align="left"&gt;
                {document.work_description}
              &lt;/CustomTableCell&gt;
              &lt;CustomTableCell align="left"&gt;
                {moment(document.date_of_commencement).format("YYYY-MM-DD")}
              &lt;/CustomTableCell&gt;
              &lt;CustomTableCell align="left"&gt;
                {moment(document.date_of_completion).format("YYYY-MM-DD")}
              &lt;/CustomTableCell&gt;
              &lt;CustomTableCell align="left"&gt;
                {document.status_of_work}
              &lt;/CustomTableCell&gt;
            &lt;/TableRow&gt;
          ))}
        &lt;/TableBody&gt;
      &lt;/Table&gt;
    &lt;/div&gt;
  );
  
    }
  }
  export default withStyles(styles)(DevelopmentList);
  </code></pre>
  
  <p>However, withing the <strong>componentDidUpdate</strong> method below, if I change it to as below the if condition (taking the length propery out of equation) then the new data is immediately rendered on the page, but then it also becomes an infinite loop inside <strong>componentDidUpdate</strong> and hitting the Express API again and again each second.</p>
  
  <pre><code>componentDidUpdate(prevProps, prevState) {
      if (
        this.state.allDevelopmentWorks !==
        prevState.allDevelopmentWorks
      ) {
        return axios
          .get("/api/developmenties")
          .then(res =&gt; {
            this.setState({
              allDevelopmentWorks: res.data
            });
  
      })
      .catch(function(error) {
        console.log(error);
      });
  }
  
   }
  </code></pre>
  
  <p>The code in the second component, (which is the child component to the main  <strong>DevelopmentList.js</strong>component, that will only open a dialog for the user to input and fill few TestFields add new data to this CRUD) is below <strong>AddNewDevelopmentWork.js</strong></p>
  
  <pre><code>class AddNewDevelopmentWork extends Component {
    state = {
      open: false,
      location: "",
      work_description: "",
      date_of_commencement: new Date(),
      date_of_completion: new Date(),
      status_of_work: "",
      vertical: "top",
      horizontal: "center"
    };
  
    handleCommencementDateChange = date =&gt; {
      this.setState({
        date_of_commencement: date
      });
    };
  
    handleCompletionDateChange = date =&gt; {
      this.setState({
        date_of_completion: date
      });
    };
  
    handleToggle = () =&gt; {
      this.setState({
        open: !this.state.open
      });        
    };
  
    handleClickOpen = () =&gt; {
      this.setState({ open: true });
    };
  
    handleClose = () =&gt; {
      this.props.history.push("/dashboard/developmentworks");
    };
  
    onChange = e =&gt; {
      const state = this.state;
      state[e.target.name] = e.target.value;
      this.setState(state);
    };
  
    handleFormSubmit = e =&gt; {
      e.preventDefault();
      const {
        location,
        work_description,
        date_of_commencement,
        date_of_completion,
        status_of_work
      } = this.state;
      axios
        .post("/api/developmenties/", {
          location,
          work_description,
          date_of_commencement,
          date_of_completion,
          status_of_work
        })
        .then(() =&gt; {
          // this.props.history.push("/dashboard/developmentworks");
          // window.location.href = window.location.href;
          this.setState({
            open: false,
            vertical: "top",
            horizontal: "center"
          });
        })
        .catch(error =&gt; {
          alert("Ooops something wrong happened, please try again");
        });
    };
  
    handleCancel = () =&gt; {
      this.setState({ open: false });
    };
  
    render() {
      const { classes } = this.props;
      const {
        location,
        work_description,
        date_of_commencement,
        date_of_completion,
        status_of_work,
        vertical,
        horizontal
      } = this.state;
  
  return (
    &lt;MuiThemeProvider theme={theme}&gt;
      &lt;MuiPickersUtilsProvider utils={DateFnsUtils}&gt;
        &lt;div&gt;
          &lt;MuiThemeProvider theme={theme}&gt;
            &lt;Dialog open={this.state.open} onClose={this.handleToggle}&gt;
              &lt;DialogContent required&gt;
                &lt;form onSubmit={this.handleFormSubmit}&gt;
                  &lt;TextField
                    value={location}
                    onChange={e =&gt;
                      this.setState({
                        location: e.target.value
                      })
                    }
                    error={location === ""}
                    helperText={
                      location === "" ? "Please enter Location" : " "
                    }
                    label="Location"
                    type="email"
                    fullWidth
                  /&gt;
                  &lt;TextField
                    value={work_description}
                    onChange={e =&gt;
                      this.setState({
                        work_description: e.target.value
                      })
                    }
                    error={work_description === ""}
                    helperText={
                      work_description === ""
                        ? "Please enter Work Description"
                        : " "
                    }
                    label="Description of Work"
                    type="email"
                    fullWidth
                  /&gt;
                  &lt;div&gt;
                    &lt;DatePicker
                      format="dd/MM/yyyy"
                      label="Date of Commencement"
                      value={date_of_commencement}
                      onChange={this.handleCommencementDateChange}
                      disableOpenOnEnter
                      animateYearScrolling={false}
                    /&gt;
                  &lt;/div&gt;
                  &lt;div&gt;
                    &lt;DatePicker
                      format="dd/MM/yyyy"
                      label="Date of Completion"
                      value={date_of_completion}
                      onChange={this.handleCompletionDateChange}
                    /&gt;
                  &lt;/div&gt;
                  &lt;TextField
                    value={status_of_work}
                    onChange={e =&gt;
                      this.setState({
                        status_of_work: e.target.value
                      })
                    }
                    error={location === ""}
                    helperText={
                      status_of_work === ""
                        ? "Please enter Status of Work!"
                        : " "
                    }
                    label="Status of Work"
                    type="email"
                    fullWidth
                  /&gt;
                &lt;/form&gt;
              &lt;/DialogContent&gt;
              &lt;DialogActions&gt;
                &lt;Button
                  onClick={this.handleCancel}
                  classes={{
                    root: classes.root
                  }}
                  variant="contained"
                &gt;
                  Cancel
                &lt;/Button&gt;
                &lt;Button
                  onClick={this.handleFormSubmit}
                  color="primary"
                  variant="contained"
                &gt;
                  Save
                &lt;/Button&gt;
              &lt;/DialogActions&gt;
            &lt;/Dialog&gt;
          &lt;/MuiThemeProvider&gt;
        &lt;/div&gt;
      &lt;/MuiPickersUtilsProvider&gt;
    &lt;/MuiThemeProvider&gt;
  );
    }
  }
  </code></pre>