非同期コンポーネントのユニットテスト
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>
);
};