componentDidUpdate 加载 API 无限次

componentDidUpdate load API infinity times

我正在从组件 B 传递来自组件 A​​ 的信息。之后根据道具 id 我调用 API 并将数据设置为状态。但是,当我调用 setState 参数来设置 API 加载的数据时, API 被有争议地调用。这是组件 B 代码:

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

为什么一直被调用?

在 componentDidMount 循环而不是 componentDidUpdate 中调用 API。

因为

if (roleId) //always true

这句话总是正确的。

也许您可以存储当前的 roleId 并进行比较

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

这仅仅是因为您的组件更新频繁,因此它一直在进行 API 调用,这是因为您在 componentDidUpdate 中进行了 API 调用。通常,您在 componentDidMount 中进行 API 调用,这将进行一次 API 调用。

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

不在

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

componentDidUpdate 运行 每次状态或道具改变。因为你在里面setState,之后它会再次运行,再次改变状态,然后无限地再次运行。在setState

前添加检查器
if ( res.data.data.permission.length != 0 && this.state.editSelectedPermisssions != res.data.data.premission) {
          this.setState({
            editSelectedPermissions: res.data.data.permission
          })
      }