93
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React の setState() の引数が関数の場合とオブジェクトの場合の違いについて整理する

Last updated at Posted at 2018-09-30

本稿のサンプルコードとデモサイトを用意しました。

概要

本稿では React の setState() の引数に関数を渡す場合と、オブジェクトを渡す場合の挙動の差異についてまとめます。

React では setState() を使って state の変更ができます。 setState() には引数に関数かオブジェクトを渡せますが、 オブジェクトを渡したときは予期せぬ動作になるかもしれないよ ということについて書きます。

サンプルアプリ

それぞれの挙動を見るにあたって下記のサンプルコードを使います。
ボタンがクリックされるたびに state.count が +1 される単純なアプリです。

import React, { Component } from "react";
import ReactDOM from "react-dom";

class Counter extends Component {
  state = {
    count: 0
  };

  render() {
    return (
      <div>
        <h1>Count: {this.state.count}</h1>
        <button onClick={this.handleClickFunction}>Count up</button>
        <button onClick={this.handleClickObject}>Count up</button>
      </div>
    );
  }

  handleClickFunction = () => {
    this.setState(prevState => {
      return { count: prevState.count + 1 };
    });
  };

  handleClickObject = () => {
    this.setState({ count: this.state.count + 1 });
  };
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Counter />, rootElement);

結果は下記のようになります。
Sep-30-2018 15-05-09.gif
ボタンをクリックするたびに 1 ずつカウントアップされています。

さて、それでは、それぞれのメソッド内で setState() を複数にした場合はどうなるでしょうか。

引数に関数を渡した場合

まずは、 setState() に関数を渡す場合について見ていきましょう。
このようにコードを書き換えた場合です。
ボタンがクリックされるたびに、state.count +2 されそうです。

...
handleClickFunction = () => {
  this.setState(prevState => {
    return { count: prevState.count + 1 };
  });
  this.setState(prevState => {
    return { count: prevState.count + 1 };
  });
};
...

結果はこのようになります。
Sep-30-2018 15-03-30.gif
いいですね。予期した動きになっています。

引数にオブジェクトを渡した場合

それでは、引数がオブジェクトの場合はどうでしょう。
コードをこのように変更します。

...
handleClickObject = () => {
  this.setState({ count: this.state.count + 1 });
  this.setState({ count: this.state.count + 1 });
};
...

結果は下記のとおりです。
Sep-30-2018 15-07-16.gif

引数にオブジェクトを渡した場合は単に、state.count に +1 した場合と同じ挙動になっています。

なぜこうなるのか

setState() は、引数に オブジェクトが渡された場合 に、 state を即時にアップデートすることを 保証しません
Reactは、パフォーマンスを高めるため、複数の setState() を単一の更新にバッチするためです。

そのため、1つの関数内で state の更新を連続的に行うときは、引数に関数を渡しましょう。

まとめ

関数を渡す場合とオブジェクトを渡す場合の違いについて書いてある記事があまりなかったので書きました。
本稿の内容は参考に載せた React のドキュメントに詳しく書いてあります。

サンプルコードとデモサイト

本稿の内容の最終的なコードを下記に用意してあります。
im36-123/differences_of_set_state
デモサイト

参考

React.Component – React
Component State – React
State and Lifecycle – React

93
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
93
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?