在下面的示例中,我使用ES6映射作为React中的状态值:
null
class App extends React.Component {
constructor(props) {
super(props);
const results = new Map();
results["group1"] = [{ value: "..." }, { value: "..." }];
this.state = { results };
}
onUpdateClick(i) {
this.state.results["group1"][i].value = i;
this.setState({});
}
onResetClick(i) {
this.state.results["group1"][i].value = "...";
this.setState({});
}
render() {
const { results } = this.state;
return (
<div>
{results["group1"].map((r, i) => (
<div>
{r.value}
<button onClick={e => this.onUpdateClick(i)}>update</button>
<button onClick={e => this.onResetClick(i)}>reset</button>
</div>
))}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='container'></div>
null
当您单击按钮时,我将直接更新映射,然后调用不带参数的setState。 我不复制这张地图。 根据我对React文档的理解,这不应该起作用,并在文档中明确警告:
千万不要直接修改this.state,因为之后调用setState()可能会替换您所做的修改。 把它当作是不可变的
(https://reactjs.org/docs/react-component.html#状态)
文档还指出比较是浅层的,因此使用空对象调用肯定不会导致合并,因此不会重新呈现?
这个例子为什么管用?
(我还应该注意到,我也在React V16.9.0中重现了这种行为)
编辑:我还想指出(因为许多答案都提到我传递的是一个空对象),如果我像这样调用setState,组件将被重新呈现(和更新):
this.setState({ results: this.state.results })
这似乎不应该引起重新渲染
来自文档:setState
除非shouldComponentUpdate()返回false,否则setState()将始终导致重新呈现。
这意味着无论是否将更改作为参数传递,this.setState({});
都将导致重新呈现
你错了:
this.setState({}); // this will do nothing.
您希望使用空对象更新状态。 但事实并非如此。
当您使用setState方法时,它期望属性更新。 但是由于您没有为setState提供任何属性,因此它将不执行任何操作。 但它仍将按setState性质重新呈现组件。
更新:到您的查询
编辑:我还想指出(因为许多答案都提到我传递的是一个空对象),如果我像这样调用setState,组件将被重新呈现(和更新):
this.setState({ results: this.state.results })
这似乎不应该引起重新渲染
React在内部声明,当您尝试用完全相同的状态更新状态时,它与this.state.results
类似。 所以,没有什么可以重新渲染的。 但是当您将setState与空对象一起使用时,React将闪烁它的状态,从而重新呈现。
从文档中阅读以下注释:
注
避免复制道具进入状态! 这是一个常见的错误:
constructor(props) {
super(props);
// Don't do this!
this.state = { color: props.color };
}
问题是它既没有必要(您可以直接使用this.props.color
),又会创建bug(颜色道具的更新不会反映在状态中)。
当调用this.setstate
时,基本上React会将传递给这个函数的参数与旧的this.state
合并,以产生一个新的状态值。 例如:
this.state = Object.assign({}, this.state, passedParam);
因此,在上面的片段中,每次调用this.setState({});
时,都会创建一个新的状态对象,使组件重新呈现。