2

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>)
}

}

shane_00
  • 101
  • 1
  • 2
  • 9
  • Since when you setState componentUpdates, when the component updates it goes into the componentDidUpdate function and sets state again. So there is an infinite loop. On the other hand componentDidMount fires only once, at the start so it doesn't get you into an infinite loop even if you setState – Sinan Yaman Dec 10 '20 at 14:25
  • why do you update the state in `componentDidUpdate` ? – Ali Faris Dec 10 '20 at 14:26
  • Does this answer your question? [ComponentDidUpdate usage and Maximum update depth exceeded](https://stackoverflow.com/questions/54388200/componentdidupdate-usage-and-maximum-update-depth-exceeded) – Sinan Yaman Dec 10 '20 at 14:26

4 Answers4

5

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({/*....*/})
    }
   }
Avi Siboni
  • 686
  • 7
  • 16
1

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

VersifiXion
  • 2,152
  • 5
  • 22
  • 40
1

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={...}/>
}
Ali Faris
  • 17,754
  • 10
  • 45
  • 70
1

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)) 
    }) 
}) 
Jakub Kurdziel
  • 3,216
  • 2
  • 12
  • 22
Jyothi
  • 29
  • 4