React setState inside componentDidUpdare leads to Maximum update depth exceeded

12.1k Views Asked by At

I am getting

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

But what I read I should be able to call setState inside componentDidMount without errors.

class MyComponent extends Component {
constructor(props) {
    super(props);
    this.state = {
        matchtedProducts: [],
        products: [],
    }
}
async componentDidMount() {
    try {
        const products = await getProducts()
        this.setState({ products })
    } catch(err) {
        console.log(err)
    }
}

componentDidUpdate() {
    const productColor = this.props.size.trim().toLowerCase()
    const productSize = this.props.color.trim().toLowerCase()
    const matches = []

    this.state.products.map(product => {
        const title = product.title
        const titleSpliitet = title.split(',')

        let color = titleSpliitet[1].trim().toLowerCase()
        let size = titleSpliitet[2].trim().toLowerCase()

        if(color == productColor && size == productSize) {
            matches.push(product)
        }

    })
    this.setState({matchtedProducts: matches})
}
render() {
    return (<div></div>)
}

}

4

There are 4 best solutions below

0
On BEST ANSWER

This happens because each setState triggers a render and then a componentDidMount again, which basically causes an infinite loop. And to stop that loop, You need to set some conditions, to prevent the render all over again, for instance

    componentDidUpdate(previousProps, previousState) {
    if (previousProps.data !== this.props.data) {
        this.setState({/*....*/})
    }
   }
0
On

I think you have to pass prevProps and/or prevState as parameter(s) of the componentDidUpdate, and execute the code only if a prop or a property of the state has changed,

Example:

componentDidUpdate(prevProps, prevState) {
  // if the property count of the state has changed
  if (prevState.count !== this.state.count) {
    // then do your code
  }
}

Docs : https://en.reactjs.org/docs/react-component.html#componentdidupdate

0
On

it seems that you want to change the state when the props changes to filter some products. I remove componentDidUpdate code and add a method in the component to do the filtering and I would call that method from the parent component

class MyComponent extends Component {
constructor(props) {
    super(props);
    this.state = {
        matchtedProducts: [],
        products: [],
    }
}
async componentDidMount() {
    try {
        const products = await getProducts()
        this.setState({ products })
    } catch(err) {
        console.log(err)
    }
}

updateMatches = () => {

    const productColor = this.props.size.trim().toLowerCase()
    const productSize = this.props.color.trim().toLowerCase()
    const matches = []

    this.state.products.map(product => {
        const title = product.title
        const titleSpliitet = title.split(',')

        let color = titleSpliitet[1].trim().toLowerCase()
        let size = titleSpliitet[2].trim().toLowerCase()

        if(color == productColor && size == productSize) {
            matches.push(product)
        }

    })
    this.setState({matchtedProducts: matches})

}

render() {
    return (<div></div>)
}

}

and in the parent component

changeSizeAndColor = () => {
     //note that I called updateMatches of MyComponent  
     this.setState({color : ... , size : ...} , () => this.myComponent.updateMatches());
}

render() { 
    return <MyComponent ref={ref => this.myComponent = ref} color={...} size={...}/>
}
0
On

I got the same error.In the use effect method, i fetched the data from the backend using axios and I updated the states. But before updating the states I didn't convert the json data to data type of the state which is why it lead to this error.

Wrong code :

Useeffect(() => {
    fetch
       .then((res) =>{
           setDate(res.data.date)
       }) 
})

Correct code :

Useeffect(() => {
    fetch
        .then((res) =>{
            setDate(new Date(res.data.date)) 
    }) 
})