そのため、React アプリケーションで問題が発生しましsetState()
た。1 つのメソッドで複数の呼び出しを行い、状態が設定された後にコードを実行する必要がある特定のケースに遭遇しました。以下のコードは、Web サイトにアカウントを追加するために使用されるダイアログ ボックスです。
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()
関数は非同期です。つまり、最終チェックの前に状態が変更されません。コードを実行する前に状態が変化するのを待つ方法をグーグルで検索しましたが、空になりました。私は今この問題を解決し、それをスタックに載せて、他の人が私が思いついた方法の恩恵を受けるかもしれないと考えました。また、私がやっていることの長所と短所、またはよりうまくいくかもしれない提案を知りたい.
グーグルで検索すると、次のようにコールバックを送信するメソッドに出くわしましたsetState()
: setState(data, callback)
. setState()
複数の通話があったため、最初はこれがうまくいくとは思いませんでした。しかし、handleSubmit()
メソッドを 3 項を使用した単一のsetState()
呼び出しに変換できることに気付きました。そのようです:
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');
})
}
状態が変更された後に匿名のコールバック関数が実行されるため、チェックが機能します。
この方法で予測される唯一の問題は、入れ子になった三項です。これは、必要に応じて非常に面倒になる可能性があるためです。これが私のプログラムに悪影響を与える可能性はありますか? または、これを解決できたより良い方法はありますか?
私の解決策で何人かの人々を助けたことを願っています。:D