Kodokon kodokon.com

品質: Testing Library、StrictMode、Profiler

実装ではなく振る舞いをテストし、StrictMode の二重呼び出しを活用し、Profiler でレンダーを測定します。

10 分 · 3 問

このレッスンを Kodokon で開く

Testing Library の哲学は一文に集約されます。ユーザーが知覚するものをテストし、実装の詳細は決してテストしない。具体的には、アクセシビリティツリー を通じて DOM をクエリします。まず getByRole(クエリの女王であり、ついでにあなたの ARIA ロールを検証してくれる)、次に getByLabelTextgetByText、そして最後の手段としてのみ getByTestId です。インタラクションには fireEvent よりも user-event を優先しましょう。fireEvent.change が孤立したイベントを発火するのに対し、user.type は本物のキーボードとまったく同じように、完全なシーケンス(focus、keydown、keypress、input、keyup)を再現します。findBy* のバリアントはクエリと非同期の待機を組み合わせます。読み込みステップの後には不可欠です。

JSX
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('adds a task to the list', async () => {
  const user = userEvent.setup();
  render(<TodoApp />);

  await user.type(
    screen.getByRole('textbox'),
    'Review the report'
  );
  await user.click(
    screen.getByRole('button', { name: /add/i })
  );

  expect(
    await screen.findByText('Review the report')
  ).toBeInTheDocument();
});
実装ではなく振る舞いに焦点を当てたテスト。

StrictMode は開発用のツールであり、本番環境ではまったく効果がありません。開発中、コンポーネント関数、state 初期化子、setState に渡された関数を 2 回 呼び出し、不純なレンダーをあぶり出します。2 回の実行が異なる結果を生むなら、隠れた副作用があるということです。React 18 以降は、各エフェクトを マウント、アンマウント、再マウント のサイクルにも通します。クリーンアップが完全に対称でないエフェクト(解除されないサブスクリプション、中断されないリクエスト)は即座に正体を現します。これは、React が state を保持したまま画面をアンマウントして再マウントする機能への直接的な準備です。

JSX
useEffect(() => {
  const controller = new AbortController();
  fetch('/api/user', { signal: controller.signal })
    .then((res) => res.json())
    .then(setUser)
    .catch(() => {});
  return () => controller.abort();
}, []);
対称的なエフェクトは StrictMode の二重マウントを乗り切ります。

測定のために、React は <Profiler> コンポーネントと、DevTools 内のそのグラフィカルな対応物を提供します。その onRender コールバックは、とりわけ phasemountupdate、または nested-update)、actualDuration(このコミットでサブツリーのレンダリングに実際に費やされた時間)、そして baseDurationメモ化を一切行わずに サブツリー全体をレンダリングする時間の見積もり)を受け取ります。両者の差はあなたの memouseMemo の有効性を測ります。actualDurationbaseDuration を大きく下回っていれば、メモ化があなたのために機能しているということです。

JSX
import { Profiler } from 'react';

function App() {
  return (
    <Profiler
      id="Sidebar"
      onRender={(id, phase, actualDuration) => {
        console.log(id, phase, actualDuration);
      }}
    >
      <Sidebar />
    </Profiler>
  );
}
サブツリーの実際のレンダーコストを測定する。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. なぜ StrictMode は開発中に各エフェクトをマウント、アンマウント、そして再マウントするのですか?
    • サーバーのネットワーク遅延をシミュレートするため
    • 各エフェクトのクリーンアップが対称的であることを確認するため
    • React の内部キャッシュをクリアするため
    • 更新のバッチ処理を強制するため
  2. Testing Library のクエリで最初に手を伸ばすべきものはどれですか?
    • getByTestId。最も安定している
    • getByClassName。最も精密
    • getByRole。アクセシビリティツリーに沿っている
    • querySelector。最も柔軟
  3. Profiler コールバックにおいて baseDuration は何を表しますか?
    • 最後のコミットの時間のみ
    • メモ化を一切行わなかった場合のサブツリーの推定レンダー時間
    • コンポーネントがマウントされてから経過した時間
    • 直近 10 回のレンダーの平均時間