gpt4 book ai didi

javascript - setState 意外更新非状态属性

转载 作者:搜寻专家 更新时间:2023-11-01 04:21:59 26 4
gpt4 key购买 nike

我不知道这是已知问题还是预期功能,但我发现了一个有趣的问题。

所以我们都知道,如果我们想在 React 中渲染一个响应式值,我们必须将值放在状态中并使用 setState:

constructor() {
super();
this.state = { counter: 0 }
this.incrementButtonListener = (e) => {
e.preventDefault();
this.setState(prevState => ({ counter: prevState.counter + 1 }));
};
}

render() {
return (
<div>
<h1>{this.state.counter}</h1>
// When clicked, counter increments by 1 and re-renders
<button onChange={this.incrementButtonListener}>Increment</button>
</div>
)
}

但是如果我们将 counter 作为字段属性,render() 只会在创建组件时捕获 counter 的快照,甚至当 counter 递增,结果不会在 render() 中响应式(Reactive)显示:

constructor() {
super();
this.counter = 0;
this.incrementButtonListener = (e) => {
e.preventDefault();
this.counter++;
};
}

render() {
return (
<div>
<h1>{this.counter}</h1>
// When clicked, counter increments by 1 but the difference is NOT rendered
<button onChange={this.incrementButtonListener}>Increment</button>
</div>
)
}

对吧?基本的东西。

但是,当我尝试摆弄这段代码时,发生了一件有趣的事情。我们将柜台作为现场属性(property),其他一切都完好无损。唯一的区别是,在 incrementButtonListener 中,我将在 someStateProperty 上添加一个 setState:

constructor() {
super();
this.counter = 0;
this.incrementButtonListener = (e) => {
e.preventDefault();
this.counter++;
/*-------------------------------ADD THIS*/
this.setState({});
// You have to pass an object, even if it's empty. this.setState() won't work.
/*-----------------------------------------*/
};
}

render() {
return (
<div>
<h1>{this.counter}</h1>
// Surprise surprise, now this.counter will update as if it was in the state!
<button onChange={this.incrementButtonListener}>Increment</button>
</div>
)
}

这一次,this.counter 更新就好像它处于状态!

所以我的假设是,每次调用 setState 时(即使使用一个空对象作为参数),render() 都会再次运行并且 this.counter 将被重新计算并因此递增。当然,它不会像国家属性(property)那样具有 100% 的 react 性。但是,在这个用例中,this.counter 唯一会改变的时间是当我点击 Increment 按钮时。因此,如果我在监听器中放置一个 setState,它就会像 this.counter 处于该状态一样工作。

现在,我不确定这是一个可接受的行为还是一个意外的黑客行为,以及我是否应该使用它。谁能帮我详细说明一下?

这是一个fiddle如果你想看到行动中的行为。您可以注释掉第 7 行中的 this.setState({}) 位以查看差异。

最佳答案

因为你没有拦截状态的变化,它会导致重新渲染,这反过来又会导致使用你增加的实例属性。这是设计使然。对 React 状态的任何更改都会导致组件重新呈现,除非您使用生命周期 Hook 来控制是否应该发生这种情况。

参见 https://reactjs.org/docs/react-component.html#shouldcomponentupdate

关于javascript - setState 意外更新非状态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51770874/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com