2
1

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 hooksとclassコンポーネントにおけるsetStateの挙動の違いについて(動かせるコードあり)

Last updated at Posted at 2020-01-20

概要

こちらは以下の記事に書いたhooksとclassコンポーネントにおけるsetStateの違いを別記事にしたものです.
https://qiita.com/yseki_/items/71511db1a60ab22ee663

忙しい人向けまとめ

hooksとクラス型コンポーネントのsetStateでは挙動が違う
hooksでは古いステートが引き継がれないため,更新の際は古いステートもセットする必要がある

それぞれのステート更新について

まずはhooksとclassのsetStateの違いを体験してみてください.
以下二つをhtmlファイルに貼り付け,お好きなブラウザで開いてみてください.
うまく動作しない場合,以下のリポジトリをcloneしてファイルをブラウザに貼り付けてください.
https://github.com/YutaSeki36/reactSetStateDiff

クラス型コンポーネント

classComponent.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ClassComponent</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div><script type="text/babel">
class ClassComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
a: 0,
b: 0
};

this.handleChangeA = this.handleChangeA.bind(this);
}

handleChangeA(a) {
this.setState({ a: this.state.a + a });
}

render() {
console.log(`a: ${this.state.a}, b: ${this.state.b}`);
return (
<div>
<p>a: {this.state.a}</p>
<p>b: {this.state.b}</p>
​
<button onClick={() => this.handleChangeA(1)}>a+1</button>
</div>
);
}
}

ReactDOM.render(<ClassComponent />, document.getElementById("root"));
</script>
</body>
</html>

関数型コンポーネント

FunctionComponent.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>FuntionComponent</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div><script type="text/babel">
const FuncComponent = props => {
const [state, setState] = React.useState({ a: 0, b: 0 });

const handleChangeA = a => {
setState({ a: state.a + a });
};

console.log(`a: ${state.a}, b: ${state.b}`);

return (
<div>
<p>a: {state.a}</p>
<p>b: {state.b}</p>
​
<button onClick={() => handleChangeA(1)}>a+1</button>
</div>
);
};

ReactDOM.render(<FuncComponent />, document.getElementById("root"));
</script>
</body>
</html>

検証

それぞれ見た目は以下のようになるかと思います.

スクリーンショット 2020-01-20 20.25.43.png

まずはクラス型コンポーネントの a+1 を押してみましょう.
スクリーンショット 2020-01-20 20.27.44.png

このように,無事更新ができました.

次は関数型コンポーネントで動作確認を行なってみましょう.

スクリーンショット 2020-01-20 20.29.37.png

このように,hooksでステートの更新を行うと,bがundefinedになってしまいました.

解決策

公式チュートリアルに,以下のような記述があります.

しかしクラスでの this.setState とは異なり、state 変数の更新は、マージではなく必ず古い値を置換します。

とありますので,hooksによるステート更新の際は古いステートもセットする必要があります.

先ほどの関数型コンポーネントファイルのステート更新mesoddo部分を以下のように書き換えます.

funcCom.html
const handleChangeA = a => {
 // スプレッド構文を用いて、古いステートも記述する
          setState({ ...state, a: state.a + a });
};

これで無事にステート更新を行うことができました.
スクリーンショット 2020-01-20 20.38.32.png

結び

あまりReactに慣れていない状態でhooksに手を出してしまい,初歩的なところで躓いてしまいました.
しっかりと公式ドキュメントにも書いている内容だったため,今後新たな技術を学ぶ際は公式ドキュメントに目を通そうと思いました.

(誤字脱字,間違った内容などあればコメントください🙇‍♂️)

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?