2016-12-07 93 views
0

所以我在我的阵营应用程序中的问题,我遇到了,我需要有一个方法多次setState()调用特定的情况下,和然后让代码运行AFTER状态被设置。以下代码是用于在网站上添加帐户的对话框。多的setState()在react方法调用:如何使它工作“同步”

import React from 'react'; 
import Dialog from 'material-ui/Dialog'; 
import FlatButton from 'material-ui/FlatButton'; 
import TextField from 'material-ui/TextField'; 

/** 
* A modal dialog can only be closed by selecting one of the actions. 
*/ 
export default class NewAcctDia extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     open: false, 
     userError: null, 
     passError: null, 
     passConfirmError: null, 
    } 

    this.handleOpen = this.handleOpen.bind(this); 
    this.handleClose = this.handleClose.bind(this); 
    this.handleSubmit = this.handleSubmit.bind(this); 
    } 

    handleOpen() { 
    this.setState({open: true}); 
    } 

    handleClose() { 
    this.setState({open: false}); 
    } 

    handleSubmit() { 
    if(!this.refs.user.getValue()) 
     this.setState({userError: "This field is required"}); 
    else 
     this.setState({userError: null}); 

    if(!this.refs.pass.getValue()) 
     this.setState({passError: "This field is required"}); 
    else 
     this.setState({passError: null}); 

    if(this.refs.pass.getValue() == this.refs.passConfirm.getValue()) { 
     this.setState({passError: null}); 
    } else { 
     this.setState({passConfirmError: "Passwords do not match"}); 
    } 

    if(!this.state.userError && !this.state.passError && !this.state.passConfirmError) 
     alert('worked'); 
    } 

    render() { 
    const actions = [ 
     <FlatButton 
     label="Cancel" 
     primary={true} 
     onTouchTap={this.handleClose} 
     />, 
     <FlatButton 
     label="Submit" 
     primary={true} 
     disabled={false} 
     onTouchTap={this.handleSubmit} 
     />, 
    ]; 

    return (
     <Dialog 
      title="Create an Account" 
      actions={actions} 
      modal={true} 
      open={this.state.open} 
      contentStyle={{width: 350}} 
     > 
      <TextField 
      ref='user' 
      floatingLabelText="Username" 
      errorText={this.state.userError} 
      /><br /> 
      <TextField 
      ref='pass' 
      floatingLabelText="Password" 
      type="password" 
      errorText={this.state.passError} 
      /><br /> 
      <TextField 
      ref='passConfirm' 
      floatingLabelText="Confirm Password" 
      type="password" 
      errorText={this.state.passConfirmError} 
      /><br /> 
     </Dialog> 
    ); 
    } 
} 

的问题是在handleSubmit()方法,我需要检查,看看用户已经进入到东西的用户名和密码字段和密码并确认匹配的密码字段。如果他们没有,我会添加错误文本到需要通过状态改变的字段。然后我试着看看状态,看看是否有错误。

不幸的是,我很快就想通了,该setState()功能是异步的,也就是说,国家将不是我的最终检查之前得到改变。我在Google上搜索并搜索了一个方法,在执行代码之前等待状态更改,但是却空了。我现在已经解决了这个问题,并且认为我会把它放在Stack上,这样其他人就可以从我提出的方法中受益。我也想知道我正在做什么的利弊,或任何可能效果更好的建议。

当我搜索周围时,我遇到了一个方法发送回拨到setState()如图所示:setState(data, callback)。我不认为这会对我起作用,因为我有多个setState()调用。但是,我意识到我可以将handleSubmit()方法转换为使用三元组的单个呼叫。像这样:

handleSubmit() { 
    this.setState({ 
     userError: (
     this.refs.user.getValue() ? null : "This field is required" 
    ), 
     passError: (
     this.refs.pass.getValue() ? null : "This field is required" 
    ), 
     passConfirmError: (
     (this.refs.pass.getValue() == this.refs.passConfirm.getValue()) ? 
      null : "Passwords do not match" 
    ) 
    },() => { 
     if(!this.state.userError && !this.state.passError && !this.state.passConfirmError) 
     alert('worked'); 
    }) 
} 

更改状态后,将执行匿名回调函数,允许我的检查工作。

我用这种方法预测的唯一问题是嵌套ternaries,因为如果需要,他们可能会变得非常混乱。这可能对我的程序有什么不利影响吗?或者我可以用更好的方法解决这个问题?

我希望我能帮助一些人解决我的问题。 :D

回答

2

反应documentation鼓励使用componentDidUpdate而不是回调参数setState

然而,如果你认为的代码似乎有点乱,尝试当地consts,使一个调用setState

handleSubmit() { 
    const {user, pass, passConfirm} = this.refs; 
    const userError = user.getValue() ? null : "This field is required"; 
    const passError = pass.getValue() ? null : "This field is required"; 
    const passConfirmError = !passError && pass.getValue() === passConfirm.getValue() 
    ? null 
    : "Passwords do not match"; 

    this.setState({userError, passError, passConfirmError}); 

    if(!userError && !emptyPassError && !passConfirmError) 
    alert('worked'); 
} 

最后,documentation还建议利用回调裁判超过串裁判:

使用ref回调只是在该类上设置属性是一种常见的用于访问DOM元素的 模式。如果您当前正在使用 this.refs.myRefName访问参考,我们建议使用此模式代替 。