2023.03.24

custom hooksのテストでuseStateが更新されないときの対処法

Reactのロゴと文字

何があった?

react-hooks-testing-libraryを使ってcustom hooksをテストした際にhooks内で作ったstateが更新されない問題が起きたのでその対処法を書き残します。

※↓はサンプルコード

import { useCallback, useState } from "react"

const useCount = () => {
  const [count, setCount] = useState<number>(0)
  const increment = useCallback(() => setCount((x) => x + 1), [])
  return {
    count: count,
    increment: increment
  }
}

export default useCount
import { renderHook } from "@testing-library/react"
import { act } from "react-dom/test-utils"
import useCount from "./count"

test("should count up", () => {
  const { result } = renderHook(() => useCount())
  const { count, increment } = result.current
  act(() => {
    increment()
    increment()
    increment()  
  })
  expect(count).toBe(3) \\ count = 0になる
})

カウントテスト.gif

解決策

当たり前のような話ですが、result.currentは現在の値しか保持してくれないらしいです。なので一回取り出すとsetStateで更新しても反映されません。ということで正しいコードは↓のようになるらしいです。

import { renderHook } from "@testing-library/react"
import { act } from "react-dom/test-utils"
import useCount from "./count"

test("should count up", () => {
  const { result } = renderHook(() => useCount())
  const { increment } = result.current
  act(() => {
    increment()
    increment()
    increment()  
  })
  expect(result.current.count).toBe(3) \\ 現在の値を取り出したいなら毎回result.currentから取り出す
})

まとめ

今回の敗因はreactのライフサイクルをきちんと把握していないせいだと思います。これに関しても一度勉強し直してまとめたほうがよいかしら...

profile

プロフィール画像

あすなろ

広告代理店で働いている新米エンジニアの技術ブログです。主にWeb技術で遊んでいます。日々楽しみながら学んでいくことを目標としています。

© Asunaro 2022