Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React Hooksのテストを書いてみよう
Search
markey
August 08, 2019
Programming
410
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Hooksのテストを書いてみよう
React Hooksのテストを書いてみよう
markey
August 08, 2019
Other Decks in Programming
See All in Programming
The Rails Doctrine Decade
koic
2
590
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
260
Workers Cache を知る
syumai
0
360
AmebaブログはKMPから卒業します
kmars0605
0
180
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
4
3.5k
IBM Bob でAI駆動開発『QC-Playbook』
ichirokano2
0
110
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.2k
[Dev Group Paris Octobre 26] Agentforce, SIforce, Claudeforce, Slackbot… on s'y retrouve ?
nabondance
0
110
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
380
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
1
430
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
AWSに止められる覚悟してますか?
morizo_1984
2
530
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
330
41k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
570
Building an army of robots
kneath
307
47k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
460
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Tell your own story through comics
letsgokoyo
1
1.1k
The Curse of the Amulet
leimatthew05
3
16k
Transcript
React Hooks のテストを書い てみよう Meguro.es #22 08/08
自己紹介 名前: markey, markey_koichan(Twitter) 職業: フロントエンドエン ジニア スキル: React/Vue/TypeScript
テスト、書いてますか?
React Hooks のテスト、書い てますか?
React Hooks 誕生後の世界 UI コンポーネント→Function Component ビジネスロジック→Custom Hook
こんないいことが UI とロジックが分離され、テスタブルなコードに ビジネスロジックをCustom Hook に集約する(API からのデータ取 得・加工、状態、ハンドラー) UI コンポーネントの開発は受け取るProps
の定義と、それらを元に した表示のみ UI コンポーネント開発者はロジック部分やAPI の仕様などを一切知 る必要がない 複数の開発者が同一ページのUI とロジックを並行開発することが可 能
今こそ、テストをやるチャン ス
それぞれのテスト UI コンポーネント→Storybook + reg-suit ビジネスロジック→@testing-library/react-hooks
今日話すのはここ UI コンポーネント→Storybook + reg-suit ビジネスロジック→@testing-library/react-hooks ビジネスロジック→@testing-library/react-hooks
@testing-library/react-hooks 公式ドキュメント React Hooks のテストユーティリティライブラリ hook をシンプルな関数のように実行でき( ラッパーコンポーネント は不要) 、
hook の更新も容易 メインのファイルはわずか93 行
パッケージの追加 yarn add --dev @testing-library/react-hooks yarn add --dev @testing-library/react-hooks #
もしくは # もしくは npm install --save-dev @testing-library/react-hooks npm install --save-dev @testing-library/react-hooks
@testing-library/react-hooks を使ったシンプルなテスト import import { { useState useState, , useCallback
useCallback } } from from 'React' 'React' export export default default function function useCounter useCounter( () ) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x return return { { count count, , increment increment } } } } import import { { renderHook renderHook } } from from '@testing-library/react-hook '@testing-library/react-hook import import useCounter useCounter from from '.' '.' test test( ('should use counter' 'should use counter', , ( () ) => => { {
ブラウザ上でのhook の動作をシミュレートして、 値を更新するには? test test( ('should increment counter' 'should increment
counter', , ( () ) => => { { const const { { result result } } = = renderHook renderHook( (( () ) => => useCounter useCounter( () )) ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) // act でラップする // act でラップする act act( (( () ) => => { { result result. .current current. .increment increment( () ) } }) ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (1 1) ) } }) )
Context から値を取得するときはどうする? (Redux, Apollo Client, ...) const const CounterStepContext CounterStepContext
= = React React. .createContext createContext( (1 1) ) export export const const CounterStepProvider CounterStepProvider = = ( ({ { step step, , children children } }) ) < <CounterStepContext CounterStepContext. .Provider value Provider value= ={ {step step} }> >{ {children children} }< < ) ) export export function function useCounter useCounter( () ) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) // increment する値はContext から取得 // increment する値はContext から取得 const const step step = = useContext useContext( (CounterStepContext CounterStepContext) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x
import import { { useCounter useCounter, , CounterStepProvider CounterStepProvider }
} from from '.' '.' test test( ('should use custom step when incrementing' 'should use custom step when incrementing', , ( () ) => => const const wrapper wrapper = = ( ({ { children children } }) ) => => ( ( < <CounterStepProvider step CounterStepProvider step= ={ {2 2} }> >{ {children children} }< </ /CounterSt CounterSt ) ) // renderHook の第2 引数にwrapper オプションを指定 // renderHook の第2 引数にwrapper オプションを指定 const const { { result result } } = = renderHook renderHook( (( () ) => => useCounter useCounter( () ), , { { w w expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) act act( (( () ) => => { { result result. .current current. .increment increment( () ) } }) )
非同期な関数の実行はどうする? export export default default function function useCounter useCounter( ()
) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x // 0.1 秒後に非同期にincrement する // 0.1 秒後に非同期にincrement する const const incrementAsync incrementAsync = = useCallback useCallback( (( () ) => => setTimeout setTimeout( (i i return return { { count count, , increment increment, , incrementAsync incrementAsync } } } }
test test( ('should increment counter after delay' 'should increment counter
after delay', , async async ( () ) = = const const { { result result, , waitForNextUpdate waitForNextUpdate } } = = renderHook renderHook( (( () ) = = result result. .current current. .incrementAsync incrementAsync( () ) // 実行直後はまだincrement されていない // 実行直後はまだincrement されていない expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) // Promise がresolve されるまで待つ // Promise がresolve されるまで待つ await await waitForNextUpdate waitForNextUpdate( () ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (1 1) ) } }) )
@testing-library/react-hooks で 快適なテストライフを
ご清聴ありがとうございまし た! ( 副業募集中...React とTypeScript チョットカケマス...)