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