私は Formsreactjs のドキュメントのセクションを読んでいて、onChange
の使用法を示すためにこのコードを試してみました( _ jsbin _ )。
var React= require('react');
var ControlledForm= React.createClass({
getInitialState: function() {
return {
value: "initial value"
};
},
handleChange: function(event) {
console.log(this.state.value);
this.setState({value: event.target.value});
console.log(this.state.value);
},
render: function() {
return (
<input type="text" value={this.state.value} onChange={this.handleChange}/>
);
}
});
React.render(
<ControlledForm/>,
document.getElementById('mount')
);
ブラウザで<input/>
値を更新すると、handleChange
コールバック内の2番目のconsole.log
は、最初のconsole.log
と同じvalue
を出力します。なぜhandleChange
コールバックのスコープ内にthis.setState({value: event.target.value})
の結果が表示されないのですか。
Reactの ドキュメンテーション :から
setState()
はすぐにthis.state
を変更するのではなく、保留状態遷移を作成します。このメソッドを呼び出した後にthis.state
にアクセスすると、既存の値が返される可能性があります。setState
への呼び出しの同期操作の保証はなく、呼び出しはパフォーマンス向上のためにバッチ処理される可能性があります。
状態が変化した後に関数を実行したい場合は、コールバックとして渡します。
this.setState({value: event.target.value}, function () {
console.log(this.state.value);
});
Reactのドキュメントで述べたように、setState
が同期的に起動されるという保証はないので、あなたのconsole.log
は更新前の状態を返すかもしれません。
Michael ParkerはsetState
内でコールバックを渡すことに言及しています。状態変更後にロジックを処理するもう1つの方法は、Reactのドキュメントで推奨されている方法であるcomponentDidUpdate
ライフサイクルメソッドを使用することです。
通常、そのようなロジックには代わりにcomponentDidUpdate()を使用することをお勧めします。
これは連続したsetState
が起動される可能性があり、すべての状態が変化した後に同じ関数を起動したい場合に特に便利です。各setState
にコールバックを追加するのではなく、必要に応じて特定のロジックを内部に置いて、関数をcomponentDidUpdate
の内部に配置できます。
// example
componentDidUpdate(prevProps, prevState) {
if (this.state.value > prevState.value) {
this.foo();
}
}
あなたはES7 async/awaitを使ってみることができます。例えばあなたの例を使って:
handleChange: async function(event) {
console.log(this.state.value);
await this.setState({value: event.target.value});
console.log(this.state.value);
}
反応するライフサイクルメソッドに気をつけてください!
私はgetDerivedStateFromProps
がsetState()
ごとに呼ばれることを知るために数時間働きました。
????
async-await
構文は、次のようなものには完璧に機能します。
changeStateFunction = () => {
// Some Worker..
this.setState((prevState) => ({
year: funcHandleYear(),
month: funcHandleMonth()
}));
goNextMonth = async () => {
await this.changeStateFunction();
const history = createBrowserHistory();
history.Push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}
goPrevMonth = async () => {
await this.changeStateFunction();
const history = createBrowserHistory();
history.Push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}
簡単に言えば - this.setState({data:value})は本質的に非同期であり、コールスタックから移動し、解決されない限りコールスタックに戻るだけです。
Event Loopについて読んで、JSの非同期性についての明確な説明と、更新に時間がかかる理由 -
https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4
だから -
this.setState({data:value});
console.log(this.state.data); // will give undefined or unupdated value
更新には時間がかかります。上記のプロセスを達成するために -
this.setState({data:value},function () {
console.log(this.state.data);
});