if _monthOffset = 12
_条件はtrueと評価され、yearOffset
状態が2017 ifyearOffset = 2018
_に更新されます。反応ドキュメントと私が読んだ他の回答に基づいて、_this.setState
_のコールバック関数は、状態が更新された後に起動しますが、console.log()
はまだ2018を出力しています。他の関連する質問からの回答に基づいてこのコードを実装するさまざまな方法がありますが、私の方法は機能しません。理由はわかりません。
_handleClick(e) {
const { monthOffset, yearOffset } = this.state
this.setState({ monthOffset: monthOffset - 1 })
if ( monthOffset - 1 === 11 ) { this.setState((prevState) => {
return { yearOffset: prevState.yearOffset - 1 } },
() => {console.log("yearOffset", yearOffset)}
)}
console.log("clicked")
}
_
おそらく、次の方法でロジックを単純化して、予期しない結果を引き起こす可能性のあるsetState
の複数の呼び出しを避けることができます。
handleClick(e) {
const { monthOffset, yearOffset } = this.state
// call setState once
this.setState({
// Always decrement month offset
monthOffset : monthOffset - 1,
// Only decrement year offset if current month offset === 12
yearOffset : (monthOffset === 12) ? yearOffset - 1 : yearOffset
}, () => {
console.log("state updated to", this.state)
})
console.log("clicked")
}
ReactでsetState
を呼び出すには、object setState
と "functional setState
" の2つの一般的なパターンがあります。 機能的なsetStateは通常、現在の状態のときに使用されます (または「前の状態」、または古い状態を呼び出したいもの) setState
呼び出しで呼び出されます。 これは、setState
が非同期であるために行われ、その結果、後続のsetStates
は、Reactが最初のsetState
サイクル。
setState
呼び出しで既存の状態を使用したため、機能的なsetState
を使用する適切な場所になります。交換
this.setState({ monthOffset: monthOffset - 1 })
と
this.setState(monthOffset => {return {monthOffset: monthOffset - 1}})
私がこれを最初に見たときにあなたが私のような人なら、あなたは「ハァッ?それは私が持っているものとどう違うの?」と思うかもしれません。違いは、setState
にオブジェクトではなく関数が渡されると、通常の解決プロセスを実行するのではなく、更新をキューに入れることです。
または、あなたはこれを考えていないかもしれません。実際には、2回目のsetState
呼び出しで関数setState
を使用しました。あなたの最初のものでもそれを使用すると、物事が正しくキューに入れられます。
ドキュメントには、コールバックは常に機能すると書かれていますが、経験から、期待どおりの結果が常に返されるとは限りません。ステート自体の内部で可変オブジェクトを使用することと関係があると思います。
ドキュメント: https://reactjs.org/docs/react-component.html#setstate
コールバックに完全に依存することはできません。代わりに、作成できるのは
var stateObject = this.state
オブジェクトに必要な変更を加えます。
stateObject.monthOffset -= 1
そして、次のように状態を設定します。
this.setState(stateObject);
そうすれば、nextState
のコピーがstateObject
の中にあります
明確にするために:状態を設定する前にすべての評価を行いたいので、次のようにします:
monthOffset -= 1
次にif (monthOffset === 12) yearOffset -=1;
その後var stateObj = {monthOffset: monthOffset, yearOffset: yearOffset}
次にthis.setState(stateObj);
ドキュメントから: "
setState()
の2番目のパラメーターは、setStateが完了してコンポーネントが完了すると実行されるオプションのコールバック関数です。 一般に、そのようなロジックの代わりにcomponentDidUpdate()を使用することをお勧めします。 "
したがって、基本的に次の状態を取得する場合は、setState()
を呼び出す関数内にそのコピーを保持するか、nextState
からcomponentDidUpdate
を取得する必要があります。
後考:パラメーターとしてsetState()
に渡すものはすべて、参照によって渡されます(値ではなく)。そのため、状態内にSearchFilters: {}
オブジェクトがあり、setState()
への呼び出し内にある場合、
setState({SearchFilters: DEFAULT_SEARCH_FILTERS}); // do not do this
「検索フィルター」と呼ばれるフォームを消去するためにSearchFilters
をDEFAULT_SEARCH_FILTERS
に設定したかもしれませんが、代わりにDEFAULT_SEARCH_FILTERS
(定数)をSearchFilters
に効果的に設定して、DEFAULT_SEARCH_FILTERS
を消去します。 。
予想される行動?教えてください。