[英]React setState inside componentDidUpdate causing infinite loop
[英]componentDidUpdate causing an infinite loop
我有这个名为 ListGyms 的父组件。 这是一个呈现表格的组件。 在表格的每一行中,您都可以看到从 API 和两个按钮中获取的健身房记录。 这些按钮呈现 2 个不同的子组件(ViewMembers 或 EditGym)。 这些子组件中的每一个都会有条件地一次呈现一个(取决于正在单击表格行中的哪个按钮)。
我的麻烦在于我的 EditGym 组件。 向 API 发送 PUT 请求时一切正常,但是,一旦调用了来自 EditGym 的 PUT 请求,ListGyms 组件不会更新其 state。
我试图在我的 ListGyms 组件中使用 componentDidUpdate() 方法使其工作,但不幸的是我的网站滞后并不断发送网络请求。 该组件卡在无限循环中。
我试图通过多种方式解决我的问题,但我失败了。 我曾尝试将 fetchingGyms 方法作为道具传递给我的子组件 EditGym,然后在提交时调用此道具 function,但出现错误 this.setState is undefined。 我真的没有想法。
这是我的代码:
ListGyms.js
import 'bootstrap/dist/css/bootstrap.min.css';
import { Spinner } from 'react-bootstrap';
import '../App.css';
import axios from 'axios';
import ViewMembers from './ViewMembers';
import EditGym from './EditGym';
import { unmountComponentAtNode } from 'react-dom';
class ListOfGyms extends React.Component {
constructor(props) {
super(props)
this.state = {
gyms: [],
isItClicked: false,
isItClickedMember: false,
isFetching: true,
checkForUpdate: true,
}
this.handleChange = this.handleChange.bind(this);
this.handleChangeForMember = this.handleChangeForMember.bind(this);
}
componentDidMount() {
this.fetchingGyms();
}
componentDidUpdate(prevProps, prevState) {
if(prevState.gyms !== this.state.gyms){
this.fetchingGyms();
}
}
async fetchingGyms(){
axios.get('https://localhost:44345/api/gyms')
.then(res => {
const gyms = res.data;
this.setState({ gyms, isFetching: false });
console.log("GYMS", gyms);
})
.catch(err => {
console.log(err);
})
}
handleChange = (e) => {
e.preventDefault();
this.setState({
isItClicked: true,
isItClickedMember: false,
id: e.target.value
}, () => {
console.log("e", e.target.value);
console.log("id", this.state.id);
});
}
handleChangeForMember = (e) =>{
this.setState({
isItClickedMember: true,
isItClicked: false,
id: e.target.value
}, () => {
console.log("e", e.target.value);
console.log("id", this.state.id);
});
}
renderTableData() {
return this.state.gyms.map((gym) => {
return (
<tr key={gym.gymID}>
<td>
<label for="gymName">Gym Name: {gym.gymName}</label>
</td>
<td>
<button value={gym.gymID} onClick={this.handleChange}>Edit</button>
</td>
<td>
<button value={gym.gymID} onClick={this.handleChangeForMember}>View Members</button>
</td>
</tr>
)
})
}
render() {
const isFetching = this.state.isFetching;
if (isFetching){
return (
<Spinner animation="border" variant="primary" />
)
}
if (this.state.isItClicked) {
return (
<>
<div class="container" className="ListOfGyms">
<div class="row">
<div class="col-sm-6">
<h2>List of Gyms</h2>
</div>
</div>
<table id='gyms' class="table table-dark">
<tbody>
{this.renderTableData()}
</tbody>
</table>
</div>
<EditGym id={this.state.id}/>
</>
)
}
if (this.state.isItClickedMember) {
return (
<>
<div class="container" className="ListOfGyms">
<div class="row">
<div class="col-sm-6">
<h2>List of Gyms</h2>
</div>
</div>
<table id='gyms' class="table table-dark">
<tbody>
{this.renderTableData()}
</tbody>
</table>
</div>
<ViewMembers id={this.state.id}/>
</>
)}
return (
<div class="container" className="ListOfGyms">
<div class="row">
<div class="col-sm-6">
<h2>List of Gyms</h2>
</div>
</div>
<table id='gyms' class="table table-dark">
<tbody>
{this.renderTableData()}
</tbody>
</table>
</div>
)
}
}
export default ListOfGyms;
EditGym.js
import React from 'react';
import axios from 'axios';
import { Spinner } from 'react-bootstrap';
class EditGym extends React.Component {
constructor(props) {
super(props);
this.state = {
GymName: '',
gym_description: '',
address_line1: '',
address_line2: '',
state: '',
postcode: '',
Country: '',
isFetching: true,
}
this.onChangeGymsName = this.onChangeGymsName.bind(this);
this.onChangeGymsDescription = this.onChangeGymsDescription.bind(this);
this.onChangeAddressLine1 = this.onChangeAddressLine1.bind(this);
this.onChangeAddressLine2 = this.onChangeAddressLine2.bind(this);
this.onChangeState = this.onChangeState.bind(this);
this.onChangePostCode = this.onChangePostCode.bind(this);
this.onChangeCountry = this.onChangeCountry.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChangeGymsName(e) {
this.setState({
GymName: e.target.value
});
}
onChangeGymsDescription(e) {
this.setState({
gym_description: e.target.value
});
}
onChangeAddressLine1(e) {
this.setState({
address_line1: e.target.value
});
}
onChangeAddressLine2(e) {
this.setState({
address_line2: e.target.value
});
}
onChangeState(e) {
this.setState({
state: e.target.value
});
}
onChangePostCode(e) {
this.setState({
postcode: e.target.value
});
}
onChangeCountry(e) {
this.setState({
Country: e.target.value
});
}
componentDidMount(){
this.setState({ isFetching: false})
}
onSubmit(e) {
var id = this.props.id;
e.preventDefault();
const obj = {
GymName: this.state.GymName,
gym_description: this.state.gym_description,
address_line1: this.state.address_line1,
address_line2: this.state.address_line2,
State: this.state.state,
postcode: this.state.postcode,
Country: this.state.Country
}
axios.put(`https://localhost:44345/api/gyms/${id}/`, obj)
.then(res => console.log(res.data));
}
render() {
const isFetching = this.state.isFetching;
if (isFetching){
return (
<Spinner animation="border" variant="primary" />
)
}
return (
<div class="form-group">
<h2>Edit the Gym Infomation</h2>
<form onSubmit={this.onSubmit}>
<div>
<label htmlFor="gymName" class="form-check-label">Gym Name</label>
<input name="gymName" value={this.state.GymName} onChange={this.onChangeGymsName} class="form-control" placeholder="Gym Name"/>
</div>
<div>
<label htmlFor="gymDescription" class="form-check-label">Description</label>
<input name="gymDescription" value={this.state.gym_description} onChange={this.onChangeGymsDescription} class="form-control" placeholder="Description"/>
</div>
<div>
<label htmlFor="addressLine1">Address Line 1</label>
<input name="addressLine1" value={this.state.address_line1} onChange={this.onChangeAddressLine1} class="form-control" placeholder="Address Line 1"/>
</div>
<div>
<label htmlFor="addressLine2">Address Line 2</label>
<input name="addressLine2" value={this.state.address_line2} onChange={this.onChangeAddressLine2} class="form-control" placeholder="Address Line 2"/>
</div>
<div>
<label htmlFor="state">State</label>
<input name="state" value={this.state.state} onChange={this.onChangeState} class="form-control" placeholder="State"/>
</div>
<div>
<label htmlFor="postCode">Postcode</label>
<input name="postCode" value={this.state.postcode} onChange={this.onChangePostCode} class="form-control" placeholder="Postcode"/>
</div>
<div>
<label htmlFor="country">Country</label>
<input name="country" value={this.state.country} onChange={this.onChangeCountry} class="form-control" placeholder="Country"/>
</div>
<button class="form-control" type="submit">Update a Gym Values</button>
</form>
</div>
)
}
}
export default EditGym;
在您的每个 onChange (handle) 方法中,您应该添加 event.preventDefault()。 这将做什么,它将防止组件在未更新时无限重新渲染。 它应该会改善您的优化。
在我看来, gyms
就像 JavaScript object。 因此, prevState.gyms
永远不会等于this.state.gyms
:
componentDidUpdate(prevProps, prevState) {
if(prevState.gyms !== this.state.gyms){
this.fetchingGyms();
}
}
你需要一个深度平等吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.