我正在根据以下页面实现以下代码:https://facebook.github.io/react/docs/forms.html
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
let data = {
isGoing: this.state.isGoing,
numberOfGuests: this.state.numberofGuests
}
/* Send data in ajax request here */
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
我对此有一些疑问:
render
函数。对我来说这没什么意义。this.setState()
之间可能存在延迟并实际使用this.state.numberOfGuests
访问状态,这意味着此代码可能会在设置之前最终获取状态?如果是这样,为什么在官方的React文档中建议使用此代码?如果没有,为什么不呢?答案 0 :(得分:5)
关于第二点,那么在handleSubmit
中的状态更新完成之前,handleInputChanged
在逻辑上可能会运行。 React文档中没有提到这个原因,或者通常是任何人都关心的原因是因为setState
函数很快就会运行真正。作为一项实验,我制作了a codepen to determine the average time taken for setState to run。它似乎需要约0.02毫秒的量级。没有人可以改变他们的输入,然后在不到那个时间内提交表单。事实上,e.preventDefault()
中的handleSubmit
电话无论如何都要花费近四分之一的时间。
如果您在继续之前完成setState
绝对至关重要的情况,那么您可以使用setState
的回调函数,例如
this.setState({
colour: 'red'
}, () => {
console.log(this.state.color)
});
然后red
将始终进行记录,而不是记录上一个值的以下内容。
this.setState({
colour: 'red'
});
console.log(this.state.color);
答案 1 :(得分:3)
非常好的问题!以下是我对他们的看法:
<强> 1。受控制或不受控制 - 这是问题
您不必使用受控表单元素。您可以使用uncontrolled并按照您在onFormSubmit处理程序中的建议获取值,例如event.isGoing.value
- 简单的JavaScript(或使用refs作为某些React文章建议)。您甚至可以通过使用defaultValue={myDefaultValue}
来猜测,设置一个不受控制的默认值。
如上所述,使用受控组件的一个原因是,如果您在用户仍在键入时希望提供实时反馈。假设您需要执行自动完成查找或提供密码强度等验证。使用状态中的值重新呈现的受控组件使这非常简单。
<强> 2。 this.setState()
异步问题?
[可能不正确],我在内部查看组件状态更新,就像队列系统一样。在处理同步代码时,对this.setState()
的调用不会丢失,也不应覆盖另一个调用。但是,可能有一段时间渲染在setState更新后面运行,但它最终将具有并呈现最新值。例如:用户键入3个字符,但他们只看到2个字符,然后很短的时间后他们会看到第3个字符。因此,有一个时间点,this.state
的读取读取了一个旧的&#34;价值,但它最终仍然更新。我希望我在这里有意义。
现在,我提到上面的同步代码,因为使用异步代码(比如使用AJAX),您可能会引入竞争条件,其中this.setState()
会覆盖较新的状态值。
答案 2 :(得分:3)
我们并不是需要将组件值存储在状态中,并且在表单提交上访问这些值完全没问题。
但是,将组件值存储在状态中有其自身的优点。这背后的主要原因是将React状态作为单一事实来源。当状态更新时(在handleInputChange
方法上),React会检查需要重新渲染的组件(或者特别是组件或子树的部分)。
使用这种方法,React帮助我们实现之前通过Two Way Binding helpers实现的目标。简而言之:
Form updated -> handleInputChange -> state updated -> updated state passed to other components accessing it
例如,您有一个<Card />
组件需要用户通过<Form />
组件输入,并且您希望在用户输入时显示信息,那么最好的方法是更新您的状态会导致React查找访问它的子树并仅重新渲染它们。因此,当您输入<Card />
时,您的<Form />
组件会自动更新。
此外,React不会为每个键入的单个字符重新呈现所有内容,而只会重新呈现需要反映文本更改的子树。请参阅React diffing algorithm了解具体方法。在这种情况下,当您在表单中的特定字段中键入字符时,只会重新呈现组件中显示该字段的那些子树。
正如React docs所述:
州更新可能是异步的
React可以将多个
setState()
个调用批处理为一个更新 性能因为
this.props
和this.state
可以异步更新,所以 应该不依赖于计算下一个状态的值。
您的代码应该可以正常工作,因为您不依赖于先前的状态来计算下一个状态,而且您还在另一个块中访问this.state
。所以你的状态更新应该反映得很好;但是,如果您不想考虑状态更新(或怀疑您的代码可能会提升以前的状态),React文档还提到了一种替代方法(实际上更好)接受function
而不是object
:
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
如果您仍然想知道何时可以安全地使用setState
方法,请在其他组件依赖的情况下使用它,或者当您不需要< strong> persist 状态(保存在本地存储或服务器中)。在处理大型项目时,最好使用状态容器来避免麻烦,例如Redux。