【问题标题】:Maximum update depth exceeded (without onclick)超过最大更新深度(没有 onclick)
【发布时间】:2019-11-12 14:48:52
【问题描述】:

我知道以前有人问过这个问题,但它似乎对我不起作用,因为我想做的是在没有 onClick 功能的情况下显示 price

我正在根据 planType 和计费设置price

代码如下:

    this.state = {
      planType: "", //populated through componentDiDMount
      billing: "", //populated through componentDiDMount
      price: 0
    };
  }

  renderPrice() {
    if (
      this.state.billing === "Monthly" &&
      this.state.planType === "Start-Up Plan"
    ) {
      this.setState({
        price: this.state.total_invoice + 35
      });
    }
  }

  render() {
    return <div>You will be charged {this.renderPrice()}</div>;
  }

【问题讨论】:

  • 不能在渲染函数中调用setState
  • 你的values是来自props吗?如果是这样,您可以使用类构造函数初始化您的状态。
  • 类构造函数
  • 您的代码可以通过对象解构进一步优化。你也可以先声明你的变量,然后在调用setState之前使用条件检查更新变量,这样你就不必多次写setState,更容易阅读!
  • 你能给我举个例子吗?

标签: reactjs


【解决方案1】:

永远不要在渲染中使用setState,有更好的方法来做你想做的事情,
我认为您希望在将billingplanType 设置为特定值时发生价格变化,为此您需要做的就是检查setStateprice 这两个值的时间和地点改变!
例如,您说这两个值是通过componentDidMount 填充的,因此您只需在该位置检查它们的值并将price 设置在那里!就这么简单。
这是一些代码:

import React, { PureComponent } from 'react';

class MyClass extends PureComponent {
    state = {
        billing: null,
        planType: null,
        total_invoice: 0,
    }

    componentDidMount() {
        //These can change through api or any other way you want!
        const newBillingType = 'Monthly';
        const newPlanType = 'Start-Up Plan';

        this.setState({ billing: newBillingType, planType: newPlanType })

        if (newBillingType === "Monthly" && newPlanType === "Start-Up Plan") {
            this.setState({ price: this.state.total_invoice + 35 })
        }
    }

    render() {

        return <div>You will be charged {this.state.price}</div>;
    }
}

export default MyClass;  

请注意,如果您像我在 componentDidMount 中所做的那样在函数内多次调用 setState(没有任何超时),因为 setState 不会立即发生,@987654333 @ 将合并结果,只做一个 setState,这是一件好事,避免了多次更新。

【讨论】:

  • 我在它不起作用之前尝试过它,我再次尝试它,现在它可以与两个 setState 一起使用。我将更新我的代码,以便您查看解决方案。谢谢!
  • @oneone,我添加了我刚才所说的示例,希望这可以解决您的问题。
  • 是的,现在我将其更改为另一个计划时遇到问题,第二个 setState 将数字覆盖为 35 eveytime。
  • @oneone 我看到了您的解决方案,您似乎忘记了 setState 不同步!不会立即发生,所以如果你调用this.state.total_invoice + 35 两次,这并不意味着70,因为state 中的值尚未更新
  • @oneone 有很多关于如何在 react 中增加内容的答案和问题,例如 stackoverflow.com/questions/39316376/…,请尝试阅读其中一些,以便您了解 react 是如何工作的,很好运气
【解决方案2】:

我实际上犹豫发布这个答案。这更像是一种优化,而不是实际的答案。但是自从@oneone要求它。我将发布一个关于如何提高代码可读性的总体思路。

真正需要考虑的一件事是,value 是否真的需要在state 中。如果该值仅用于计算其他一些值,也许您不必将其存储在 state 中。当然我不知道代码的实际实现,所以你必须自己弄清楚。

class Component extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      // Do consider if billing / planType is actually necessary to be in state.
      billing: null,
      planType: null,
      price: 0,
      total_invoice: 0,
    };
  } 

  componentDidMount() {
    const { total_invoice } = this.state; 

    const newBilling = 'Monthly';
    const newPlanType = 'Start-Up Plan';

    // default price
    let price = total_invoice;

    this.setState({ billing: newBilling, planType: newPlanType }, () => {
      const { planType } = this.state; 
      // setState callback, state values here are guaranteed to be updated.
      switch (planType) {
        case 'Start-Up Plan':
          price = total_invoice + 35;
          break;
        case 'Standard Plan':
          price = total_invoice + 65;
          break;
        default:
      }
      this.setState({ price });
    });
  }

  render() {
    const { price } = this.state;
    return (
      <div>
        You will be charged {price}
      </div>
    )
  }
}

【讨论】:

  • 非常感谢,这100%解决了我的问题!我从未见过有人像您那样在其他地方使用 setState 。在此之前,由于两个 setStates,我得到了一个错误。但现在它就像一个魅力!
  • 一般这种类型的数据变动真的不需要等billingplanType改价再尝试改价,如果等的话,你实际上是在调用@987654326 @ 两次并在您没有​​真正拥有时导致额外的更新!,我认为这是一种不好的做法,应该避免。
  • 是的。通常你应该只调用一次setState。我知道我的代码会触发两次重新渲染。顺便说一下,您的回答也会两次致电setState。这就是为什么我在我的代码中有一个注释说明如果billingplanType 确实需要作为一个状态。如果它只是用于计算其他值,也许你不需要它在一个状态中。当然最终还是要看作者想做什么。
  • 我在回答中确实注意到,如果您像在 componentDidMount 中那样多次调用函数内部的 setState(没有任何超时),因为 setState 不会立即发生,React 将结合结果和只做一个 setState,避免多次更新
猜你喜欢
  • 2020-01-04
  • 1970-01-01
  • 2021-06-30
  • 2021-07-12
  • 2019-04-03
  • 2019-02-14
  • 2019-07-17
  • 2019-12-13
  • 2019-05-28
相关资源
最近更新 更多