Reactjs 反应:组件';调用此.setState()后,不会调用s render()

Reactjs 反应:组件';调用此.setState()后,不会调用s render(),reactjs,Reactjs,使用this.setState()更改状态后,不会调用我的组件的render()方法 这是更改组件状态的方法(调用了该方法,我已对此进行了验证): 这是组件的初始状态: constructor(props) { super(props); this.state = { contactPhone: [{ phoneNumber: '', phoneType: '' }], }; } 以下是文本字段的呈现方式: {contactPhone.map((p

使用
this.setState()
更改状态后,不会调用我的组件的
render()
方法

这是更改组件状态的方法(调用了该方法,我已对此进行了验证):

这是组件的初始状态:

  constructor(props) {
    super(props);

    this.state = {
      contactPhone: [{ phoneNumber: '', phoneType: '' }],
    };
  }
以下是文本字段的呈现方式:

{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>
))}
{contactPhone.map((电话,索引)=>(

))}

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

将列表键指定给一个随机字符串化的数字,
key={String(Math.random())}
,这是一个糟糕的主意,因为每次调用render时,该键都会发生变化,并且在调用
此.setState
时无法正确协调虚拟DOM。React通过使用相同的键区分列表项来跟踪哪些列表项已更改

有关React对账的更多详细信息,请参见下面的链接:

我认为您需要重新访问您的
handlePhoneNumberChange
功能: 您在这里不进行更改,而是两次设置相同的值。
阵列
联系人电话
的参考相同

handlePhoneNumberChange = name => (event) => {
    // its destructed, but not changed later
    const { contactPhone } = this.state;
    //  no changes
    const index = name;
    const phoneEntry = contactPhone[index];
    phoneEntry.phoneNumber = event.target.value;

    // you set same value, nothing changed
    this.setState({ contactPhone });
  };

您没有在此处修改状态。您正在将其设置为初始值。 更新代码如下

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 });
致:


[…contactPhone]
只需创建一个新对象。但是现在正在调用render()。非常奇怪。

您的
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.slice(0);


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

尝试
onChange={this.handlePhoneNumberChange.bind(index,this)}
this并进行检查。我使用的是ES6哈希火箭表示法,所以我不知道这可能是什么问题
TextField
。你能展示一下组件吗?可能prop
onChange
未附加到DOM节点?看,这是你的代码,在联系前和联系后,电话值是相同的和更改的。你是对的!这是你的问题。来自文档:切勿直接对this.state进行变异,因为之后调用setState()可能会替换您所做的变异。把这个状态当作是不变的。这和我的问题有什么关系?它和你的问题有一切关系。假设您的代码中没有其他错误,因为缺少很多东西,所以我必须假设“有效”。如果输入的键从一种状态更改为下一种状态,React将不知道发生了什么变化。但是为什么不调用render()?是否可以通过在其中写入console.log来验证是否正在调用您的
handlePhoneNumberChange
。如果你把你的代码放在[CodeSandbox](www.codesandox.com)上,我可以更详细地看一看。你的contactPhone阵列永远不会改变。您只需将其从当前状态中解构,然后在不做任何更改的情况下将其放回。为什么我不进行更改
phoneEntry
只是对数组中元素的引用
contactPhone
。请在此处添加注释以说明您的目标,因为此处没有任何更改
contactPhone
setState
之后与之前的
setState
相同
Array
不一样。请阅读密码。如果是相同的呢?如果是相同的,组件不会重新加载为什么不呢?我不同意这只会在contactPhone数组中添加一个新元素,为什么要这样做?如果不更改状态,为什么要触发render()?但是,如果您想强制使用渲染方法,可以尝试使用contactPhone=[…contactPhone]更改状态,然后设置state?我正在更改状态。这是有效的,因为数组与我在注释或回答中指出的不相同。…您的回答是contactPhone数组不会更改。确实如此。我不知道为什么会这样。我已经评论了
我认为contactPhone的引用没有改变,这就是react无法理解contactPhone改变的原因。
我之前和之后都记录了contactPhone。它正在改变。我仍然不知道为什么会这样。@etayluz是的,它正在改变你是对的!!!但引用并没有,这就是react-setstate不理解变量已更改的原因,也是它不再调用呈现函数的原因。您确定要编写“反结构化语法”吗?这是一个不同于你展示的概念。也许你是想说“扩展语法”?对!我会调整答案的。我想弄清楚那里发生了什么,但我把这个词弄错了。谢谢虽然您的解决方案是正确的,但我仍在试图弄清楚为什么在setState之后不调用render()。即使不复制contactPhone阵列,状态也会发生变化。我已经通过手动调用render()验证了这一点,并通过将状态记录在那里验证了状态是否发生了变化。这对我来说仍然是个谜。很奇怪。这必须是React.js的内部内容,没有适当的文档记录或解释。请查看。我不认为您使用的是
React.PureComponent
,但是示例和示例可能会对这个问题有更多的帮助。
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);