blog

Reactのレビュー -setState

updater: 更新された状態のステートオブジェクトを返す関数型で、ステートに浅くマージされます。 callback: オプションのコールバック関数。 オブジェクト型で、入力されたオブジェクトを新...

Sep 30, 2020 · 5 min. read
シェア

setStateの概要

setStateは、Reactが状態を管理するための重要なメソッドです。

setState公式の使い方

  1. 構文1: setState(updater[, callback])
    • updater: 関数型で、更新された状態のstateオブジェクトを返します。
    • callback: オプション、コールバック関数。
this.setState((state, props) => ({ counter: state.counter + props.increment }));
  1. 構文 2: setState(stateChange[, callback])
    • stateChange: オブジェクト型で、入力されたオブジェクトを新しい状態に浅くマージします。
    • callback: オプション。
// 公式には、この方法は推奨されていない。.props および this.state 非同期で更新される可能性があるので、以下で詳しく説明するように、次の状態を更新するためにその値を当てにしてはいけない。
this.setState({
 counter: this.state.counter + this.props.increment,
});

setStateの第2パラメータについて:

2番目のパラメータは、setState関数が呼び出され、コンポーネントが再レンダリングを開始したときに呼び出されるコールバック関数です。

setState を使用する際のいくつかのポイント

なぜreactは this.stateで変更しないのですか?

// 状態を更新する
this.setState({count: count + 1})
//  
this.state.count = count + 1

なぜなら、ステートは単なるオブジェクトであり、オブジェクトの値を変更するだけでは意味がないからです。考えてみてください。Reactコンポーネントを再描画させることなく、this.stateの値を変更するだけなら、何の意味があるでしょうか?

この時点で、状態の更新とコンポーネントの更新処理の両方を実行できる関数が必要で、その関数がsetStateです。

setStateは this.stateの値を直ちに変更するものではありません。

function incrementMultiple() {
 this.setState({count: this.state.count + 1});
 this.setState({count: this.state.count + 1});
 this.setState({count: this.state.count + 1});
}

incrementMultipleが呼び出されると、コンポーネントの状態のカウント値が3回インクリメントされ、setStateを呼び出すたびにカウント値が1回インクリメントされるはずですが、実際にはカウント値は1回しかインクリメントされません。なぜなら、this.setStateの呼び出しは this.stateをすぐに変更しないので、this.setStateは同じ値を何度も設定しているだけだからです。なぜなら、this.setStateの呼び出しは this.stateをすぐには変更しないので、this.setStateは同じ値を何度も設定しているだけだからです。

setStatethisを変更するタイミング.state

setStateは、コンポーネントの更新処理をトリガーして再描画をトリガーします setStateは、結果としてReactの更新ライフサイクル関数を呼び出します 4つの関数

  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

あるいは、shouldComponentUpdateがfalseを返すと、更新処理は中断され、render関数は呼び出されません。しかし、Reactは this.stateの更新をあきらめないので、renderを呼び出さなくても this.stateは更新されます。

複数の setState 関数呼び出しによって生成された効果はマージされます。

あなたの州が複数の個別の変数を含む場合

constructor(props) {
 super(props);
 this.state = {
 posts: [],
 comments: []
 };
 }

setState を個別に呼び出すことで、それぞれの状態を個別に更新できます。

 componentDidMount() {
 fetchPosts().then(response => {
 this.setState({
 posts: response.posts
 });
 });
 fetchComments().then(response => {
 this.setState({
 comments: response.comments
 });
 });
}

this".setStateは2回連続で呼び出されますが、更新のライフサイクルをトリガーするのは1回だけで、2回ではありません。なぜなら、Reactは複数の this.setStateによって生成された変更をキューに入れ、それらを保存し、準備ができたと感じたときに更新をトリガーするからです。this".setStateのたびに更新処理をトリガーするのは無駄だからです!

setStateに関数updaterを渡すことができます。

この関数は2つの引数を取ります。1つ目は現在のステート値、2つ目は現在のプロップスで、this.stateに望ましい変化を表すオブジェクトを返すはずです。しかし、このオブジェクトの計算は少し変更され、this.stateに依存しなくなり、入力パラメータのstateに依存するようになりました。

では、上の状態のカウントを増やす例を書き直してみましょう:

function increment(state, props) { return {count: state.count + 1}; }

見ての通り、stateのカウントにも1が追加されていますが、stateのソースは this.stateではなく、入力パラメータのstateです。

function incrementMultiple() {
 this.setState(increment);
 this.setState(increment);
 this.setState(increment);
}

関数setStateを複数回呼び出す場合、Reactは、インクリメントが呼び出されるたびに、ステートがステートの修正結果をマージしたことを確認します。

簡単に言えば、現在の this.state.countの値が0であることを追加すると、最初の呼び出し this.setState(increment)は、インクリメントに渡された状態パラメータは0であり、2回目の呼び出しの状態パラメータは1であり、3回目の呼び出しは2であり、incrementMultipleの最終的な効果は、本当に this.stateパラメータが2であることです。が0である場合、2回目の呼び出しは、状態のパラメータは1であり、3回目の呼び出しは、パラメータは2であり、incrementMultipleの最終的な効果は、本当に this.state.countを3にすることです。

this".stateは、increment関数が呼び出された時点では変更されず、render関数が再実行されるまで変更されないことは特筆に値します。

setStateの非同期と同期の問題

つまり、setStateを呼び出した後、Reactコンポーネントを再レンダリングする必要があり、レンダリング後に this.stateの状態が変更されます。しかし、setStateは同期的にコンポーネントを更新するのでしょうか。つまり、setState関数が戻ったときには、this.stateはすでに状態の変更を反映しているのでしょうか。この答えはイエスです。

Reactでは、イベントがReactによって発生した場合、setStateの呼び出しは this.stateを同期的に更新しません。そうでない場合、setStateの呼び出しは this.stateを同期的に実行します。の状態を更新します。

in addition to」とはどういう意味ですか?ReactのaddEventListenerや、setTimeout/setIntervalで生成される非同期コールをバイパスするイベントハンドラを意味します。

Reactを規律正しく使えば、"other than "を扱う必要はありません。開発のほとんどは、onChange、onClick、onTouchMoveなど、Reactによってカプセル化されたイベントを使用し、これらのイベントハンドラのsetStateは非同期で処理されます。

栗として。

constructor() {
 this.state = {
 count: 10
 }
 this.handleClickOne = this.handleClickOne.bind(this)
 this.handleClickTwo = this.handleClickTwo.bind(this)
}
render() {
 return (
 <button onClick={this.hanldeClickOne}>clickOne</button>
 <button onClick={this.hanldeClickTwo}>clickTwo</button>
 <button id="btn">clickTwo</button>
 )
}
handleClickOne() {
 this.setState({ count: this.state.count + 1})
 console.log(this.state.count)
}

出力:10

これは、ReactのラップイベントハンドラのsetStateが非同期に状態を更新することを示しています。

componentDidMount() { document.getElementById('btn').addEventListener('clcik', () => { this.setState({ count: this.state.count + 1}) console.log(this.state.count) }) }

出力:11

handleClickTwo() { setTimeout(() => { this.setState({ count: this.state.count + 1}) console.log(this.state.count) }, 10) }

出力:11

Reactは非同期と同期をどのように制御するのですか?

Read next

デザイン・パターン入門 - シングルトン・パターン

シングルトンパターンは、一般的に使用されるソフトウェアの設計パターンであり、定義は、クラスのオブジェクトの単一のインスタンスは、1つだけ存在するインスタンスを許可することができますです。 多くの場合、システム全体が1つだけのグローバルオブジェクトを持つ必要があり、システム全体の振る舞いを調整するのに役立ちます。例えば、サーバープログラムでは、サーバーの設定情報はファイルに保存され、設定データはオブジェクトの単一のインスタンスによって読み取られ、その後、サービスプロセス内の他のオブジェクトが...

Sep 30, 2020 · 5 min read