みなさんこんにちは。宮水です。
今日は、Hooksを完全に理解します。
Hooksってなに?
Hooksは、React16.8で追加された新機能です。
これを使うと、今までclassコンポーネントでしかできなかった機能が関数コンポーネントで使えるようになります。
フックの導入 – React
useStateとか、useEffectなどの関数があります。
classコンポーネントでしかできなかったことって何?
Stateの管理と、ライフサイクルメソッドの利用です。
関数コンポーネントは、コンポーネントを返すことしかできませんでした。
しかしHooksを利用すると、関数コンポーネントでもStateの管理とライフサイクルメソッドの利用ができるようになります。
どうして関数コンポーネントがいいの?
こちらはわからなくて会社の人に質問させていただいたのですが、公式ドキュメントに答えが載ってました!!
Introducing Hooks – React
classコンポーネントだと、
- thisを理解する必要がある
- イベントハンドラーをbindする必要がある
- コードが冗長になる
- 処理が重くなることがある
などのデメリットがあるようです。
確かに、classコンポーネントと比べると関数コンポーネントの方がコード量も少ないしすごく読みやすいです。
私が2年くらい前にReactが全然理解できなくて学習をやめてしまった理由に、classコンポーネントの書き方が複雑だったからだということに気づきました。
hooksにはどんな関数があるの?
以下のような関数があります。
useState...関数コンポーネントで、コンポーネントレベルでstateが使えるようになる。
useEffect...関数コンポーネントで、ライフサイクルメソッドが使えるようになる。
useContext...関数コンポーネントで、コンテキストシステムが使えるようになる。
useRef...関数コンポーネントでRefシステムが使えるようになる。
useReducer...関数コンポーネントで、Reducerを通してStoreを使えるようになる。
useStateの使い方
classコンポーネントで書いた場合
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
hooksを使って、関数コンポーネントで書いた場合
import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
いずれも公式ドキュメントより引用しました。
useStateの説明
const [count, setCount] = useState(0);
それぞれ、
count = 現在の値
setCount = this.setState({ count })と同じ意味。
0 = 初期値。state = { count: 0 }と同じ意味。
です。
奇妙な構文にみえますが、
colors = ["red", "green"] colors[0] // => "red" colors[1] // => "green" [color1, color2] = colors color1 // => "red" color2 // => "green"
と同じ構文です。
コンポーネントがクリックされてsetCountが発動したら、useStateによってcountの値が再代入されてstateが変更されるということなんですね!
useEffectの使い方
classコンポーネントの場合
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
hooksを使って関数コンポーネントで書いた場合
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
useEffectの説明
useEffectを理解するには、ライフサイクルメソッドを知る必要があります。
componentDidMount...ComponentがMountされた後に実行されるメソッドです。
componentDidUpdate...Componentのpropsかstateが変更されたときに実行されます。
そしてuseEffectは、componentDidMountとcomponentDidUpdateの機能を持った関数です。
useEffectの第2引数について
useEffect(() => { ... }, [])
useEffectでは、第二引数に空の配列を渡す構文もあります。
この空の配列を書くことで、第2引数の配列に渡されたstateが変更されたときだけ処理を実行することができます。
useEffect(() => { ... }, [1]) ↓ // useEffectは呼ばれる useEffect(() => { ... }, [10])
オブジェクトの中身が同じでもオブジェクトIDが異なるとuseEffectは呼ばれます。
useEffect(() => { ... }, [{color: "red"}]) ↓ // オブジェクトの中身は同じでも、オブジェクトIDが異なるとuseEffectは呼ばれる。(例えば、Reduxを使用しているときに出くわすパターンです。Reduxを介して作成されたオブジェクトは、たとえ中身が同じでも関数を通す前と後では全く違うオブジェクトです。) useEffect(() => { ... }, [{color: "red"}])
終わりに
以上がhooks入門でした!
使い方や構文の意味はわかったけど、なんでclassコンポーネントのままじゃダメなのかわからないので、まだまだReactの意味を理解できてないのかも。再び復習していきます!
参考文献
- このUdemyが英語ですがめちゃくちゃわかりやすいのでおすすめです!
Modern React with Redux Training Course
- 公式ドキュメント
- React Component ライフサイクル ひとめぐり (CodeSandbox 付き)