Celt67
Celt67

Reputation: 27

How to update state of component in componentDidUpdate() without being stuck in an infinite re render?

I have a component with a componentDidMount() method that calls a method called getData() which gets the initial data and sets the initial state of the component.

class LogsSettings extends React.Component {
constructor(props) {
    super(props);

    this.settingsUrls = [
        "/ui/settings/logging"
    ];

    this.state = {
        configSettings: {},
        formSchema: formSchema
    };

    this.configSettings = {};
    this.selected = "general";

}

    getData = (url, selectedSetting) => {
    fetch(url)
        .then((response) => {
                if (response.status !== 200) {
                    console.log('Looks like there was a problem. Status Code: ' +
                        response.status);
                    return;
                }
                response.json().then((response) => {
                    //pass formschema here
                    console.log(selectedSetting);
                    let newFormSchema = this.setNonDefaultValues(response.data, formSchema.subsections);
                    Object.assign(this.configSettings, response.data);
                    this.setState({
                       configSettings : this.configSettings,
                        formSchema: newFormSchema
                   });
                });
            }
        )
        .catch((err) => {
            console.log('Fetch Error :-S', err);
        });
};


componentDidMount() {
    this.settingsUrls.map((settingUrl) => {
        this.getData(settingUrl, this.selected)

})

}

componentDidUpdate() {
    this.settingsUrls.map((settingUrl) => {
        this.getData(settingUrl, this.props.selectedSetting)

})

}



render() {

    return (
        <div className="card-wrapper">
            <h2>{formSchema.label.toUpperCase()}</h2>
            {
                formSchema.subsections.map((subSection) => {
                    return (
                        <>
                            <h3>{subSection['description']}</h3>
                            <div style={{marginBottom: '10px'}}></div>

                            {
                                subSection['input_fields'].map((inputField) => {
                                    return buildForm(inputField, this.handleChange)
                                })
                            }
                            <hr></hr>
                        </>
                    )
                })
            }
            <button className="button button-primary">Save Changes</button>
        </div>
    )
}

}

The selectedSetting parameter that gets passed to the getData() method in this component will change however and when this changes, I need to change the state of the component and get new data specific to the changed selectedSetting parameter.

The new selectedSetting is passed into the component as a prop. The problem is that I can't pass the new selectedSetting parameter to my getData method to update the state of the component as it gets caught in an infinite loop.

How do I go about passing the new selectedSetting to the getData() method without getting caught in an infinite loop? Is this even possible? If not, what is the best approach I should take?

note the selectedSetting parameter isn't used in the getData() function yet but will be and it will be used to get data from an API call and a new form schema which will then lead to the ConfigSettings and formSchema states being changed

Upvotes: 0

Views: 152

Answers (1)

Franrey Saycon
Franrey Saycon

Reputation: 667

If you look closely on the lifecycle of your component, after mount, you'll fetch then update the component. This will trigger the componentDidUpdate lifecycle method which will do the same thing, causing the infinite loop. You need to have a flag that checks whether this.props.selected changed. If it didn't, don't fetch the data else fetch as normal. In the update method, you have access to the previous props. (You may also do this in componentShouldUpdate method, but it'll be just outright risky)

componentDidUpdate(prevProps) {
    if( prevProps.selectedSetting !== this.props.selectedSetting ){
       this.settingsUrls.map((settingUrl) => {
         this.getData(settingUrl, this.props.selectedSetting)
      })
    }
}

also just a heads up, I noticed that your didMount method, uses a default of "general" as the selected setting, since you want to be using this.props.selectedSetting might be better if it was the one being used instead and just set default props to "general".

Upvotes: 1

Related Questions