【问题标题】:React setState inside componentDidUpdare leads to Maximum update depth exceeded在 componentDidUpdare 中反应 setState 导致超过最大更新深度
【发布时间】:2021-03-21 23:37:54
【问题描述】:

我得到了

错误:超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。

但我读到的内容应该可以在 componentDidMount 中调用 setState 而不会出错。

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

}

【问题讨论】:

  • 自从你setState componentUpdates,当组件更新它进入componentDidUpdate函数并再次设置状态。所以有一个无限循环。另一方面 componentDidMount 在开始时只触发一次,因此即使您 setState 也不会让您进入无限循环
  • 为什么要更新componentDidUpdate中的状态?

标签: javascript reactjs setstate react-lifecycle


【解决方案1】:

发生这种情况是因为每个 setState 都会触发一次渲染,然后再次触发 componentDidMount,这基本上会导致无限循环。 为了停止该循环,您需要设置一些条件,以防止重新渲染,例如

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

【讨论】:

    【解决方案2】:

    似乎您想在道具更改时更改状态以过滤某些产品。 我删除了componentDidUpdate 代码并在组件中添加了一个方法来进行过滤,我会从父组件中调用该方法

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

    在父组件中

    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={...}/>
    }
    

    【讨论】:

      【解决方案3】:

      我认为您必须将prevProps 和/或prevState 作为componentDidUpdate 的参数传递,并且仅在状态的道具或属性发生更改时才执行代码,

      例子:

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

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

      【讨论】:

        猜你喜欢
        • 2021-07-12
        • 2019-02-14
        • 2019-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-21
        • 2021-05-15
        • 2020-01-11
        相关资源
        最近更新 更多