reactjs.org
こちら公式サイトで Basic Hooks と呼ばれてる useState と useEffect と useContext のみ実装してみます
Additional Hooks については、また今度にしますが、useReducer など Redux の reducer のような機能もあって面白そうです
まだ Hooks は v16.7 の α 版の機能なので、以下を実行
yarn add react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0 -D
今回作成したコードは以下のリポジトリにあります github.com ベースに使用したボイラープレートが TSX でしたが、今回の Hooks は TypeScript で書いてないです
useState
Function Component で State を扱えるようになる
useState に値を渡すとそれを初期値にしたState
とそのStateを更新する関数
を配列で返す
import React, { useState } from 'react' const UseState = () => { const [count, setCount] = useState(1) return ( <div> <p>########## UseState ##########</p> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> <p>########## UseState ##########</p> </div> ) } export default UseState
useEffect
React のライフサイクル関数の代わりとなるもの
useEffect の第 1 引数に実行する関数、第 2 引数に変更を watch する要素を配列で追加する
第 2 引数に指定した配列内の要素のいずれかが更新されたら、第 1 引数の関数を実行する
import React, { useEffect, useState } from 'react' const UseEffect = () => { const [effect1, setEffect1] = useState(0) const [effect2, setEffect2] = useState(0) const [effect3, setEffect3] = useState(0) const [count, setCount] = useState(0) useEffect(() => setEffect1(effect1 + 1)) useEffect(() => setEffect2(effect2 + 1), [count]) useEffect(() => setEffect3(effect3 + 1), []) return ( <div> <p>########## UseEffect ##########</p> <p>Effect1: {effect1}</p> <p>Effect2: {effect2}</p> <p>Effect3: {effect3}</p> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Click me</button> <p>########## UseEffect ##########</p> </div> ) } export default UseEffect
effect1 は、useEffect で第 2 引数を渡してないので、常に第 1 引数の関数が呼ばれ続ける
⇒ このような使い方は通常やらないと思う
effect2 は、useEffect で第 2 引数に count を渡しているので、count が変更された時のみ第 1 引数の関数を呼び出す
⇒ componentDidMount + componentDidUpdate の呼び出しのように使えそう
effect3 は、useEffect で第 2 引数に空配列を渡しており、最初のマウント時のみ第 1 引数の関数を呼び出す
⇒ componentDidMount の呼び出しのように使えそう
useContext
Context を利用するための Hook
ContextAPI の Provider にセットした State を useContext で受け取ってみます
import React, { useContext } from 'react' const Context = React.createContext() const { Provider } = Context // Function Component での Provider の作り方の正解がよく分からないので、一旦 class を使っている class SetProvider extends React.Component { constructor(props) { super(props) this.state = { count: 2 } } render() { return ( <Provider value={{ state: this.state }}> <UseContext /> </Provider> ) } } const UseContext = () => { const context = useContext(Context) return ( <div> <p>########## UseContext ##########</p> <p>Context.count: {context.state.count}</p> <p>########## UseContext ##########</p> </div> ) } export default SetProvider