2017-07-17 17 views
0

年、月、日の選択ドロップダウンを持つフォームがあります。ReactJSで日付を作成する年月日を組み合わせる

<select onChange={(event) => this.mergeDate('day', event.target.value)}> 
    <option value="1">1</option> 
    ... 
</select> 

<select onChange={(event) => this.mergeDate('month', event.target.value)}> 
    <option value="1">January</option> 
    ... 
</select> 

<select onChange={(event) => this.mergeDate('year', event.target.value)}> 
    <option value="1977">1e977</option> 
    ... 
</select> 

私は、これらの値のうち、日付を作成し、状態のbirthdayフィールドに保存する必要があります。これを行うために、私はdate_day,date_mthおよびdate_yearという3つの追加プロパティを作成しました。

this.state = { 
         name: '', 
         email: '', 
         birthday: '', 
         country: '', 
         date_day: '', 
         date_mth: '', 
         date_year: '' 
       }  

し、Selectドロップダウン変化に、私は次のようにDate()機能を使用して値をマージ機能作成:この機能で

mergeDate(type, value) 
{ 

     if (type === 'year') { this.setState({ date_year: value }) } 
     if (type === 'month') { this.setState({ date_mth: value }) } 
     if (type === 'day') { this.setState({ date_day: value }) } 

     console.log('merging date now '); // --> Works! 

     let newDate = new Date(this.state.date_year, this.state.date_mth, this.state.date_day); 

     console.log(newDate);    // --> successful, but shows date value of last onChange event 

     this.setState({ birthday: newDate }); 

     console.log(this.state);   // --> {...., birthday: '', ....} 

} 

は、第二にconsole.logは最後に設定された日付を表示しますonChangeイベント。最後のconsole.logは、空の値をbirthdayに記録します。私はまだ理解していないsetStateasynchronous behaviorのために問題を推測しています。問題の背後に理由と解決策を教えてください。

==========

UPDATE

アサド、setStateによるにパラメータとして渡されるべきasynchronousあると状態を設定した後に行われる任意のアクションが完了しましたsetState関数。私は試しました:

postUpdate() 
{ 
     let newDate = new Date(this.state.date_year, this.state.date_mth, this.state.date_day); 
     this.setState({ birthday : newDate }); 
} 

mergeDate(type, value) 
{ 
     if (type === 'year') { this.setState({ date_year:value }, this.postUpdate(newDate))} 
     if (type === 'month') { this.setState({ date_mth: value }, this.postUpdate(newDate))} 
     if (type === 'day') { this.setState({ date_day: value }, this.postUpdate(newDate))}  
} 

これは私には同じ出力を与えています - 最後のonChangeイベントの日付値を示しています。私は何が欠けていますか?

========

SOLUTION

溶液は単独ではなく関数としての機能を渡さないことです。

mergeDate(type, value) 
{ 
     if (type === 'year') { this.setState({ date_year:value },() => this.postUpdate())} 
     if (type === 'month') { this.setState({ date_mth: value },() => this.postUpdate())} 
     if (type === 'day') { this.setState({ date_day: value },() => this.postUpdate())}  
} 
+0

'setState'は非同期であることを覚えておく必要があります。それの後ろで処理したい場合は、2番目の引数としてコールバックを渡す必要があります。 –

+0

答えてくれてありがとう、Asad。私はどのようなコールバックを送るべきですか? – anonym

+0

あなたの問題は、あなたが実際に関数を渡すのではなく、呼び出すということです。私のコードに書かれているのと同じ方法で、 'this.setState({date_day:value}、postUpdate)'のように渡すだけです。あなたの場合、メソッドとして設定したので、 '、this.postUpdate.bind(this))'が必要ですが、その時点であなたがすでにやっていることはおそらく読みやすくなります。 –

答えて

1

setStateは非同期です。これは、Reactがパフォーマンスの更新を頻繁にバッチするためです。これは、setStateのステートメントで新しい状態が利用可能であることに頼ることができないことを意味します。あなたは変化の順序に依存している場合、あなたはそのように、コールバックを渡す必要があります。一般的には

mergeDate(type, value) 
{ 
     function postUpdate() { 
      // All of the code from after your if statements 
     } 
     if (type === 'year') { this.setState({ date_year: value }, postUpdate) } 
     if (type === 'month') { this.setState({ date_mth: value }, postUpdate) } 
     if (type === 'day') { this.setState({ date_day: value }, postUpdate) } 

} 

をしかし、あなたは、単に前までのすべてのあなたの計算をやっている必要がありますだけで、関数の最後で一度setStateを呼び出します状態へのあなたのすべての望ましい変更。

+0

私の質問をご覧ください。 – anonym

+0

私はそれを理解しました。情報はとても役に立ちました、ありがとう。 – anonym

+0

@anonym申し訳ありません、当時はオフラインでしたが、うれしく思いました。 –

関連する問題