react:在调用 this.setState() 后不会调用组件的 render()

IT技术 reactjs
2021-05-02 09:17:54

我的组件的render()方法在使用this.setState().

这是更改组件状态的方法(它被调用并且我已经验证了这一点):

  handlePhoneNumberChange = name => (event) => {
    const { contactPhone } = this.state;

    const index = name;
    const phoneEntry = contactPhone[index];
    phoneEntry.phoneNumber = event.target.value;
    this.setState({ contactPhone });
  };

这是组件的初始状态:

  constructor(props) {
    super(props);

    this.state = {
      contactPhone: [{ phoneNumber: '', phoneType: '' }],
    };
  }

这是 TextField 的呈现方式:

{contactPhone.map((phone, index) => (
    <div key={index}>
                <TextField
                  id={String(Math.random())}
                  label="Phone number"
                  type="tel"
                  value={phone.phoneNumber}
                  onChange={this.handlePhoneNumberChange(index)}
                  placeholder="Contact phone number"
                  margin="normal"
                />
                <br />
    </div>
))}

为什么在 setState() 之后不调用渲染?

4个回答

您的handlePhoneNumberChange函数直接改变状态。React文档指出永远不要直接改变 this.state,因为之后调用 setState() 可能会替换你所做的改变。将 this.state 视为不可变的。

最简单的修复方法是克隆contactPhone,更改它并将其传递给 state

handlePhoneNumberChange = index => (event) => {
  const contactPhone = [...this.state.contactPhone]; // at this point contactPhone !== this.state.contactPhone
  const phoneEntry = contactPhone[index];
  phoneEntry.phoneNumber = event.target.value;
  this.setState({ contactPhone });
};

应该管用!


const cloneArray = [...someArray]; // spread syntax

是相同的

const cloneArray = someArray.slice(0);

两者都产生一个数组,该数组包含相同的值someArray但不是相同的数组。

将列表键分配给随机字符串化数字是一个糟糕的主意key={String(Math.random())},因为键会随着每次渲染调用而改变,并且 React 在this.setState调用时将无法正确协调虚拟 DOM React 通过比较具有相同键的列表项来跟踪哪些列表项已更改。

有关 React 协调的更多详细信息,请参阅以下链接:https : //reactjs.org/docs/reconciliation.html#keys

您不是在此处修改状态。您将其设置为与最初相同的值。更新代码如下。

handlePhoneNumberChange = name => (event) => {
    const { contactPhone } = this.state;
    const index = name;
    const phoneEntry = contactPhone[index];
    phoneEntry.phoneNumber = event.target.value;
    contactPhone = [...contactPhone,phoneEntry]
    this.setState({ contactPhone });
};

我不知道它为什么有效,但它解决了它:

我变了:

this.setState({ contactPhone });

到:

this.setState({ contactPhone: [...contactPhone] });

[...contactPhone]简单地创建一个新对象。但是现在正在调用 render() 。很奇怪。