访问 this.state 后如何确保 setState 调用已经执行?
Posted
技术标签:
【中文标题】访问 this.state 后如何确保 setState 调用已经执行?【英文标题】:How to make sure the setState calls are already executed after accessing this.state? 【发布时间】:2021-04-06 11:04:49 【问题描述】:我有一个注册表。当我单击 Register 按钮时,所有TextInputs
都已验证,并且对于每个字段,我都会调用一个函数,我在其中调用例如this.setState(usernameError: 'This field is required')
。
因此,对于每个文本字段,我都有一个函数来设置该字段的错误状态。在我按下 Register 按钮后,我想验证所有字段,然后如果状态中有任何字段错误,则返回该函数(如果所有字段都没有正确填写,用户可能无法注册)。问题是:因为setState
是异步的,所以不保证我检查的时候所有的字段错误都已经正确设置了。
2 个重要注释:
-
我知道 setState 的第二个参数(回调),但我无法执行此回调中的条件(检查状态中的字段错误),因为 setState 调用位于它们自己的函数中
它们位于自己的函数中,因为我想重用逻辑(我也在其他地方调用
validate<FieldName>
函数,例如当onChangeText
事件发生时)
所以我的问题是:如何确保在检查其值时已更新状态而不放弃我可重用的“验证器函数”?
一些代码使其更清晰:
state = usernameError: '', firstNameError: '', lastNameError: '' ;
setUsernameError = () => // This function is also called elsewhere than in handlePressRegister
const username = this.state;
if (username === '')
this.setState( usernameError: 'Required field' );
else if (username.length < 2)
this.setState( usernameError: 'Minimum 2 characters' );
else
this.setState( usernameError: undefined );
setFirstNameError = () => // This function is also called elsewhere than in handlePressRegister
...shortened for brevity...
setLastNameError = () => // This function is also called elsewhere than in handlePressRegister
...shortened for brevity...
handlePressRegister = () =>
const usernameError, firstNameError, lastNameError = this.state;
this.setUsernameError();
this.setFirstNameError();
this.setLastNameError();
if (usernameError || firstNameError || lastNameError) // The errors may not be set in the state yet
return;
希望你能正确理解我的问题。
【问题讨论】:
您是否将组件的state
传递给一个不是 React 组件的函数以重用该函数?
【参考方案1】:
我会通过让各种set[X]Error
函数返回它们的新值来处理这个问题。例如:
setUsernameError = () =>
const username = this.state;
let error = undefined;
if (username === '')
error = 'Required field';
else if (username.length < 2)
error = 'Minimum 2 characters';
this.setState( usernameError: error );
return error;
handlePressRegister = () =>
const usernameError = this.setUsernameError();
const firstNameError = this.setFirstNameError();
const lastNameError = this.setLastNameError();
if (usernameError || firstNameError || lastNameError)
return;
// ...
【讨论】:
【参考方案2】:如果您promisifysetState
,您可以从每个验证器调用中返回它并在其上调用Promise.all
:
setUsernameError = () => // This function is also called elsewhere than in handlePressRegister
const username = this.state;
if (username === '')
return setStatePromisified( usernameError: 'Required field' );
// ...
Promise.all([
this.setUsernameError(),
this.setFirstNameError(),
this.setLastNameError(),
])
.then(() =>
// state will be updated now
const usernameError, firstNameError, lastNameError = this.state;
if (usernameError || firstNameError || lastNameError)
return;
// submit?
);
另一种选择是将另一个属性添加到状态中,例如validating
,当按下注册按钮时会设置该属性。下一次渲染,在componentDidUpdate
中检测其变化,重置validating
,并根据需要继续执行逻辑(如果没有错误则提交表单?)。
【讨论】:
以上是关于访问 this.state 后如何确保 setState 调用已经执行?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们需要在 ReactJS 中使用 bind() 来访问 this.props 或 this.state? [复制]
当第二次访问屏幕时,React Native null不是对象(评估'_this2.state.data')错误