反应状态更新但在渲染时不显示

React state updating but not showing while render

我正在研究react,我做了一个表格来用react保存数据, 我想在保存数据时再次更新 table,为此我使用了 setState,问题是状态更新而不是渲染,我已经尝试了一些方法来找到问题,

  1. 通过使用console.log()发现状态正在正常改变
  2. 渲染功能在更改状态后正常工作

这是我的代码

import React, { Component } from "react";
import Header from "../header";
import Table from "./table";
import Addbox from "./create__box";
import $ from "jquery";
import { Api__url } from "../../vars";

class index extends Component {
  constructor(props) {
    super(props);
    // binding functions
    this.getData = this.getData.bind(this);
    this.table = this.table.bind(this);
    this.show_create_box = this.show_create_box.bind(this);
    // using state
    this.state = {
      data: "Fetching Records....",
      create_box: "",
    };
  }

  getData() {
    $.ajax({
      type: "POST",
      url: `${Api__url}services/get`,
      dataType: "JSON",
      success: this.table,
    });
  }

  table(d) {
    this.setState({ data: <Table data={d} /> });
  }

  show_create_box() {
    this.setState({create_box: <Addbox top="15vh" again_get_data={this.getData}/>});
  }

  componentDidMount() {
    this.getData();
  }

  render() {
    return (
      <>
        <Header />
        <div className="container mt-5 px-5">
          <div className="border__box p-2 col">
            <div className="row m-0 px-3">
              <div className="col">
                <h2>Services in home page</h2>
              </div>
              <div className="col d-flex justify-content-end">
                <button
                  onClick={this.show_create_box}
                  className="btn btn-outline-success show__create__box"
                >
                  Add New Data
                </button>
              </div>
            </div>
            <div className="row m-0 py-2 px-4">{this.state.data}</div>
          </div>
        </div>
        {this.state.create_box}
      </>
    );
  }
}

export default index;

```

the code from the table file
```
import React, { Component } from "react";
import Updatebox from "./update__box";

class table extends Component {
  constructor(props) {
    super(props);
    this.show_update_box = this.show_update_box.bind(this);
    this.delete_record = this.delete_record.bind(this);
    this.state = { update_box: "" };

    // making data
    this.tbody = props.data.map((d, index) => {
      return (
        <tr className="w-100 row m-0 p-0" id={d.services_id}>
          <th className="col-1" scope="row">
            {index + 1}
          </th>
          <td className="col-3">{d.services_name}</td>
          <td className="col-4">{d.services_description}</td>
          <td className="col-2">{d.services_icon}</td>
          <td className="col-1">
            <button
              onClick={() => {
                this.show_update_box(index);
              }}
              className="btn btn-outline-success"
            >
              Update
            </button>
          </td>
          <td className="col-1">
            <button
              onClick={() => {
                this.delete_record(index);
              }}
              className="btn btn-outline-danger"
            >
              Delete
            </button>
          </td>
        </tr>
      );
    });
  }

  // Function to get close form instruction from another class
  changeStuff(d) {
    this.setState(d);
  }

  delete_record(id) {
    alert(id);
  }

  show_update_box(key) {
    this.setState({
      update_box: (
        <Updatebox
          data={this.props.data[key]}
          changeHandler={this.changeStuff.bind(this)}
        />
      ),
    });
  }

  render() {
    return (
      <>
        <table className="position-relative table table-hover ">
          <thead className="table-dark">
            <tr className="row m-0 p-0">
              <th className="col-1">Sr #</th>
              <th className="col-3">Name</th>
              <th className="col-4">Description</th>
              <th className="col-2">Icon</th>
              <th className="col-1">Update</th>
              <th className="col-1">Delete</th>
            </tr>
          </thead>
          <tbody>{this.tbody}</tbody>
        </table>
        {this.state.update_box}
      </>
    );
  }
}

export default table;

```

here's the code for creating the box
```
import React, { Component } from "react";
import CloseIcon from "@mui/icons-material/Close";
import $ from "jquery";
// import i from "./index";

export default class Addbox extends Component {
  constructor(props) {
    super(props);
    this.data = { name: "", description: "", icon: "" };
    this.state = this.data;
    this.change = this.change.bind(this);
    this.submit = this.submit.bind(this);
    this.changeCSS = this.changeCSS.bind(this);
    this.setCSS = this.setCSS.bind(this);
    this.close_create_box = this.close_create_box.bind(this);
  }

  close_create_box() {
    this.props.changeHandler({ create_box: "" });
  }

  change(e) {
    var name = e.target.name;
    var value = e.target.value;
    this.setState({
      [name]: value,
    });
  }

  changeCSS() {
    $("#create").removeClass("btn-outline-success");
    $("#create").addClass("btn-outline-dark");
    $("#create").prop("disabled", true);
    $("#create").text("Sending....");
  }

  setCSS() {
    $("#create").removeClass("btn-outline-dark");
    $("#create").addClass("btn-outline-success");
    $("#create").prop("disabled", false);
    $("#create").text("Submit");
  }

  submit(e) {
    e.preventDefault();
    $.ajax({
      type: "POST",
      url: "http://127.0.0.1:8000/api/services/create",
      data: this.state,
      dataType: "JSON",
      beforeSend: this.changeCSS,
      success: (e) => {
        alert(e.message);
        this.props.again_get_data();
        this.close_create_box();
      },
      error: (e) => {
        this.setCSS();
        alert(e.responseText);
      },
    });
  }

  render() {
    return (
      <form
        onSubmit={this.submit}
        className="add__box create__box"
        method="POST"
        style={{ top: this.props.top }}
      >
        <div className="mb-3 row">
          <div className="col-10">
            <h4>Add New Service</h4>
          </div>
          <div className="col-2">
            <CloseIcon className="close" onClick={this.close_create_box} />
          </div>
        </div>
        <div className="mb-3">
          <label htmlFor="create_name" className="form-label">
            Name
          </label>
          <input
            id="create_name"
            name="name"
            type="text"
            className="form-control"
            onChange={this.change}
            value={this.state.name}
            required
            minLength={10}
            maxLength={100}
          />
        </div>
        <div className="mb-3">
          <label htmlFor="create_desc" className="form-label">
            Description
          </label>
          <textarea
            id="create_desc"
            className="form-control"
            onChange={this.change}
            required
            value={this.state.description}
            minLength={20}
            name="description"
          ></textarea>
        </div>
        <div className="mb-3">
          <label htmlFor="create_icon" className="form-label">
            Icon
          </label>
          <input
            id="create_icon"
            type="text"
            className="form-control"
            onChange={this.change}
            value={this.state.icon}
            required
            name="icon"
          />
        </div>
        <div className="m-5 row my-0">
          <button id="create" type="submit" className="btn btn-outline-success">
            Submit
          </button>
        </div>
      </form>
    );
  }
}

```

根据 react docs,UI 组件不应该处于状态,它应该只包含表示您的 UI 状态所需的最少数据量。

因此,与其在状态中添加 UI 元素,不如在其中添加最少量的数据

这是一个基于您的代码的示例

constructor(props) {
   ...
   this.state = {
     status: "loading",
     data: "Fetching Records....",
     create_box: "",
   };
}

table(d) {
  this.setState({ data: d, status: "table" });
}

renderData() {
   const d = this.state.data
   const status = this.state.status
   if (status == "loading") { return d }
   if (status == "table") { return <Table data={d} /> }
}

render() {
    return (
      <>
        ...
        <div className="row m-0 py-2 px-4">{renderData()}</div>
        ...
      </>
    );
}