Hooks(useState, useEffect)の動作確認

React16.8で追加された「Hooks」を利用して、関数コンポーネントに「state」と「ライフサイクルメソッド」の機能を実装する方法を確認します。

useState|state

概要

useState() を利用すると、コンポーネントの状態管理を実装できます。

  • useState() の引数にstateの初期値を指定する。
  • useState() は戻り値として、state変数stateを更新するための関数 を返す。
  • 複数のstateを使うには、複数回 useState() を呼ぶ。

動作確認

import React, { useState } from 'react'

const App = ({ message }) => {
  const [items, setItems] = useState(Array(9).fill(0))
  const [flg, setFlg] = useState(false)

  const handleClickItem = index => {
    if (!flg) {
      setFlg(true)
    }

    const newItems = items.slice()
    newItems[index]++
    setItems(newItems)
  }

  const handleResetItems = () => {
    setFlg(false)
    setItems(Array(9).fill(0))
  }

  return (
    <div>
      <p>{flg && message}</p>
      <ul>{items.map((item, index) => {
        return (
          <li
            key={index}
            onClick={() => handleClickItem(index)}
          >
            {`Button${index}: ${item}`}
          </li>
        )
      })}</ul>
      <div onClick={handleResetItems}>Reset items</div>
    </div>
  )
}

export default App
702-react-hooks_image.gif

実行イメージです。

devtools(3.6.0)でArrayの中身が表示されないようです。下記issueが作られていました。
https://github.com/facebook/react-devtools/issues/1282

参考

useEffect|ライフサイクルの代替

概要

useEffect() は、クラスコンポーネントの以下メソッドが持つ役割をまとめたものです。

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

useEffect() の動作の特徴です。

  • 第一引数(関数指定)
    • componentDidMount componentDidUpdate で行っていた処理を指定する。
    • 関数の戻り値( return )の指定は任意。
      • 戻り値( return )で指定した処理が、コンポーネントの終了時に実行される。
        ( componentWillUnmount に相当 )
  • 第二引数(配列指定)
    • 第一引数で指定した関数の実行タイミングを調整
    • 指定しない場合、初回レンダー時毎回の更新時 に実行される。
    • 空配列で指定した場合( [] )
      • 初回レンダー時 のみ実行される。
    • 特定stateを指定した場合( e.g. [state1, state3] )
      • 初回レンダー時指定stateの更新時 に実行される。

動作確認
( デフォルト )

import React, { useState, useEffect } from 'react'

const App = () => {
  const [state1, setState1] = useState(0)
  const [state2, setState2] = useState(0)

  useEffect(() => {
    console.log('useEffect')
  })

  const handleClickState1 = () => {
    setState1(state1 + 1)
  }

  const handleClickState2 = () => {
    setState2(state2 + 1)
  }

  return (
    <div>
      <p>{`state1: ${state1} state2: ${state2}`}</p>
      <div onClick={handleClickState1}>Click1</div>
      <div onClick={handleClickState2}>Click2</div>
    </div>
  )
}

export default App
702-react-hooks_effect1.gif

useEffectの第二引数を指定していません。

初回レンダー時毎回の更新時 にコンソール出力されています。

動作確認
( 初回と特定state更新時に実行 )

import React, { useState, useEffect } from 'react'

const App = () => {
  const [state1, setState1] = useState(0)
  const [state2, setState2] = useState(0)

  useEffect(() => {
    console.log('useEffect')
  }, [state1])

  const handleClickState1 = () => {
    setState1(state1 + 1)
  }

  const handleClickState2 = () => {
    setState2(state2 + 1)
  }

  return (
    <div>
      <p>{`state1: ${state1} state2: ${state2}`}</p>
      <div onClick={handleClickState1}>Click1</div>
      <div onClick={handleClickState2}>Click2</div>
    </div>
  )
}

export default App
702-react-hooks_effect2.gif

useEffectの第二引数でstate1のみ指定してます。

初回レンダー時state1の更新時 にコンソール出力されています。

動作確認
( 初回だけ実行 )

import React, { useState, useEffect } from 'react'

const App = () => {
  const [state1, setState1] = useState(0)
  const [state2, setState2] = useState(0)

  useEffect(() => {
    console.log('useEffect')
  }, [])

  const handleClickState1 = () => {
    setState1(state1 + 1)
  }

  const handleClickState2 = () => {
    setState2(state2 + 1)
  }

  return (
    <div>
      <p>{`state1: ${state1} state2: ${state2}`}</p>
      <div onClick={handleClickState1}>Click1</div>
      <div onClick={handleClickState2}>Click2</div>
    </div>
  )
}

export default App
702-react-hooks_effect3.gif

useEffectの第二引数で空配列を指定してます。

初回レンダー時 のみコンソール出力されています。

参考

参考