FR STAR
FR STAR

Reputation: 702

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?

Upvotes: 0

Views: 61

Answers (4)

Hagai Harari
Hagai Harari

Reputation: 2877

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
          })
      } 

Upvotes: 1

Friday Ameh
Friday Ameh

Reputation: 1684

It is simply because your component update frequently as such it keeps making the API call and this is because you are making the API call in componentDidUpdate. Usually, you make the API call in componentDidMount, this will make the API call once.

async componentDidMount() {
      this.props.getPermission();
      const res = await axios.get(`http://localhost:3000/v1/permissions/role/${roleId}/`); // should be make here
  }

Not in

componentDidUpdate(){
  //Avoid Making API calls here
}

Upvotes: 0

Sabster
Sabster

Reputation: 51

It's because

if (roleId) //always true

this statement is always true.

Maybe you could store current roleId and and do the comparision

if (this.state.currentRoleId !== 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({
        currentRoleId: roleId,
        editSelectedPermissions: res.data.data.permission
      })
  } 
}
 

Upvotes: 0

Bilal
Bilal

Reputation: 25

Call API in componentDidMount cycle rather than in componentDidUpdate.

Upvotes: 0

Related Questions