Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21089

React hooksとclassコンポーネントにおけるsetStateの挙動の違いについて(動かせるコードあり)

$
0
0

概要

こちらは以下の記事に書いた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><metacharset="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><divid="root"></div><script type="text/babel">classClassComponentextendsReact.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>
​<buttononClick={()=>this.handleChangeA(1)}>a+1</button>
</div>
);}}ReactDOM.render(<ClassComponent/>,document.getElementById("root"));</script></body></html>

関数型コンポーネント

FunctionComponent.html
<!DOCTYPE html><html><head><metacharset="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><divid="root"></div><script type="text/babel">constFuncComponent=props=>{const[state,setState]=React.useState({a:0,b:0});consthandleChangeA=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>
​<buttononClick={()=>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に手を出してしまい,初歩的なところで躓いてしまいました.
しっかりと公式ドキュメントにも書いている内容だったため,今後新たな技術を学ぶ際は公式ドキュメントに目を通そうと思いました.

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


Viewing all articles
Browse latest Browse all 21089

Trending Articles