非同期コンポーネントのユニットテスト

date
Jan 2, 2023
repo_url
slug
async-component
status
Published
summary
type
Post
thumbnail_url
tags
jest
outer_link
以下はテキストボックスの横に入力した値を表示するコンポーネントです。
import React, { useState, useCallback, useRef } from 'react';

type DelayButtonProps = {
  onChange: React.ChangeEventHandler<HTMLInputElement>;
};

export const DelayInput = (props: DelayButtonProps) => {
  const { onChange } = props;
  // 入力中かどうか保持する状態
  const [isTyping, setIsTyping] = useState(false);
  // inputに表示するテキストを保持する状態
  const [inputValue, setInputValue] = useState('');
  // spanに表示するテキストを保持する状態
  const [viewValue, setViewValue] = useState('');
  // タイマーを保持するRef
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // テキスト入力中の処理
  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      // 入力中のフラグをセット
      setIsTyping(true);
      // inputに表示するテキストを更新する
      setInputValue(e.target.value);
      // もしtimerRefに以前設定したタイマーがある場合は先に解除する
      if (timerRef.current !== null) {
        clearTimeout(timerRef.current);
      }
      // 1秒後にタイマーをセットする
      timerRef.current = setTimeout(() => {
        timerRef.current = null;
        // 入力中のフラグを解除
        setIsTyping(false);
        // spanに表示するテキストを更新する
        setViewValue(e.target.value);
        // onChangeコールバックを呼ぶ
        onChange(e);
      }, 1000);
    },
    [onChange]
  );
  // spanに表示するテキスト
  const text = isTyping ? '入力中…' : `入力したテキスト:${viewValue}`;

  return (
    <div>
      {/* data-testidはテスト中だけ使用するID */}
      <input
        data-testid='input-text'
        value={inputValue}
        onChange={handleChange}
        type='text'
      />
      <span data-testid='display-text'>{text}</span>
    </div>
  );
};
DelayInput/index.tsx
 

© Hayato Kamiyama 2023 - 2024 - Build with Next.js & Notion