繁体   English   中英

componentDidUpdate 导致无限循环

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM