import React, { Component } from 'react';
class Counter extends Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
decrement = () => {
this.setState(prevState => ({
value: prevState.value - 1
}));
};
render() {
return (
<div>
{this.state.value}
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
}
通常我看到的是,如果他使用 es6 类,人们会在构造函数中执行 this.state。如果他不是,他可能会使用 getinitialstate 函数来设置状态。但是上面的代码(是的,它是一个工作代码),两者都没有使用。我有两个问题,这里的状态是什么?那是局部变量吗?如果是,为什么它没有 const
? prevState 从哪里来?为什么在setState中使用箭头函数?只做 this.setState({value:'something'})
不是很容易吗?
最佳答案
I have 2 question, what is
state
here?
实例属性,例如在构造函数中设置 this.state = {value: 0};
。它使用 Public Class Fields proposal目前处于阶段 2。(increment
和 decrement
也是如此,它们是实例字段,其值是箭头函数,因此它们关闭 this
。)
is that a local variable?
没有。
where does the prevState come from? why arrow function is used in setState? isn't it's easy to just do this.setState({value:'something'})?
来自 the documentation :
React may batch multiple
setState()
calls into a single update for performance.Because
this.props
andthis.state
may be updated asynchronously, you should not rely on their values for calculating the next state.For example, this code may fail to update the counter:
// Wrong this.setState({ counter: this.state.counter + this.props.increment, });
To fix it, use a second form of
setState()
that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:// Correct this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));
...这正是引用的代码所做的。这是错误的:
// Wrong
increment = () => {
this.setState({
value: this.state.value + 1
});
};
...因为它依赖于 this.state
的状态,上面告诉我们不要这样做;所以引用的代码改为这样做:
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
这里证明了 React 可能以一种不明显的方式批量调用,以及为什么我们需要使用 setState
的回调版本:这里,我们有 increment
和 decrement
每次点击被调用 两次 而不是一次(一次通过按钮,一次通过包含按钮的范围)。单击 +
一次 应该将计数器增加到 2,因为 increment
被调用了两次。但是因为我们没有使用 setState
的函数回调版本,所以它不会:其中一个对 increment
的调用变成了空操作,因为我们使用了一个过时的 this.state.value
值:
class Counter extends React.Component {
state = { value: 0 };
increment = () => {
/*
this.setState(prevState => ({
value: prevState.value + 1
}));
*/
console.log("increment called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value + 1
});
};
fooup = () => {
this.increment();
};
decrement = () => {
/*
this.setState(prevState => ({
value: prevState.value - 1
}));
*/
console.log("decrement called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value - 1
});
};
foodown = () => {
this.decrement();
};
render() {
return (
<div>
{this.state.value}
<span onClick={this.fooup}>
<button onClick={this.increment}>+</button>
</span>
<span onClick={this.foodown}>
<button onClick={this.decrement}>-</button>
</span>
</div>
)
}
}
ReactDOM.render(
<Counter />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
通过函数回调,它可以正常工作(没有调用 increment
变成空操作):
class Counter extends React.Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => {
console.log("Incrementing, prevState.value = " + prevState.value);
return {
value: prevState.value + 1
};
});
};
fooup = () => {
this.increment();
};
decrement = () => {
this.setState(prevState => {
console.log("Decrementing, prevState.value = " + prevState.value);
return {
value: prevState.value - 1
};
});
};
foodown = () => {
this.decrement();
};
render() {
return (
<div>
{this.state.value}
<span onClick={this.fooup}>
<button onClick={this.increment}>+</button>
</span>
<span onClick={this.foodown}>
<button onClick={this.decrement}>-</button>
</span>
</div>
)
}
}
ReactDOM.render(
<Counter />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
在这种情况下,当然,我们可以查看 render
方法并说“嘿,increment
将在单击期间被调用两次,我最好使用setState
的回调版本。”但是,与其假设在确定下一个状态时使用 this.state
是安全的,最佳做法是不这样假设。在一个复杂的组件中,很容易以一种 mutator 方法的作者可能没有想到的方式使用 mutator 方法。因此 React 作者的声明:
Because
this.props
andthis.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
关于javascript - react 中没有构造函数的初始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42993989/