反应状态更新但在渲染时不显示
React state updating but not showing while render
我正在研究react,我做了一个表格来用react保存数据,
我想在保存数据时再次更新 table,为此我使用了 setState,问题是状态更新而不是渲染,我已经尝试了一些方法来找到问题,
- 通过使用console.log()发现状态正在正常改变
- 渲染功能在更改状态后正常工作
这是我的代码
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>
...
</>
);
}
我正在研究react,我做了一个表格来用react保存数据, 我想在保存数据时再次更新 table,为此我使用了 setState,问题是状态更新而不是渲染,我已经尝试了一些方法来找到问题,
- 通过使用console.log()发现状态正在正常改变
- 渲染功能在更改状态后正常工作
这是我的代码
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>
...
</>
);
}