Search code examples
javascriptreactjsreact-lifecycle

componentDidUpdate load API infinity times


I'm passing information from Component A from the Component B. After that depending on the props id I'm calling an API and setting the data to states. However, when I called the setState parameter to set the the API loaded data, the API were been called contentiously. Here's the Component B code:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Modal from "react-bootstrap/Modal";
import PropTypes from 'prop-types'
import axios from 'axios';

import TextBox from '../../layouts/textBox'

import { getPermission } from '../../actions/permissionActions';

class Form extends Component {
 
  state = {
    editSelectedPermissions: []
  }


  async componentDidMount() {
   this.props.getPermission();
  }

  async componentDidUpdate() {
    const roleId = this.getRoleId();

    if (roleId) {
      const res = await axios.get(`http://localhost:3000/v1/permissions/role/${roleId}/`);
      console.log(res.data.data);
      if ( res.data.data.permission.length != 0) {
          this.setState({
            editSelectedPermissions: res.data.data.permission
          })
      } 
    }
  }

  getRoleId=()=> this.props.data.id

  render() {

    const { onCloseModal, onSubmit, onChange, onCheckBox, permissions } = this.props;

    const { showModal, id, name, description} = this.props.data;

   const { editSelectedPermissions } = this.state;

    let selectedPermission = false;

    return (
      <div>
        <Modal show={showModal} centered onHide={onCloseModal}>
          <Modal.Header closeButton>{id ? "Edit" : "Add"} User Role</Modal.Header>
          <Modal.Body>
            <form onSubmit={onSubmit.bind(this)}>

              <input type="hidden" name="id" value={id} />

              <div className="form-row">
                <div className="col-md-6">
                  <TextBox type="text" name="name" placeholder="Enter Name" label="Name" value={name} onChange={onChange} />
                </div>
                <div className="col-md-6">
                  <TextBox type="text" name="description" placeholder="Enter Description" label="Description" value={description} onChange={onChange} />
                </div>
              </div>
              
              {permissions.map((item, index) => {

                if (editSelectedPermissions.length > 0)
                  selectedPermission = editSelectedPermissions.find((item2) => item2.id === item.id)

                return (
                  <div className="form-check" key={index}>
                    <input className="form-check-input"  type="checkbox" name="permission" checked={selectedPermission} onChange={onCheckBox} value={item.id}/>
                    <label className="form-check-label" htmlFor="defaultCheck1">
                      {item.name}
                    </label>
                  </div>
                )
              })}

              <div className="d-flex justify-content-center">
                <input
                  type="submit"
                  className="btn btn-primary"
                  value={id ? "Edit Record" : "Create Record"}  
                />
              </div>
            </form>
          </Modal.Body>
        </Modal>
      </div>
    );
  }
}

Form.propTypes = {
  getPermission: PropTypes.func.isRequired,
}

const mapStateToProps = (state) => ({
  permissions: state.permission.permissions
});

export default connect(mapStateToProps,  {getPermission} )(Form);

Any reason why it's been called continuously?


Solution

  • componentDidUpdate run each time state or props change. Because you setState inside, after it it will run again, change state again, and run again infinitely. Add checker before setState

    if ( res.data.data.permission.length != 0 && this.state.editSelectedPermisssions != res.data.data.premission) {
              this.setState({
                editSelectedPermissions: res.data.data.permission
              })
          }