目次
前提
↓前回の記事 に機能追加します
追加・減らすボタンを押した時以外に input入力中にエンター・空欄時にバックスペースで input を増減できるようにします
特定のキー入力で関数を作動
const onKeydown = (key) => {
switch (key) {
case 'Enter':
// ここにエンターを押した時の処理を記述
break;
case 'Backspace':
// ここにバックスペースを押した時の処理を記述
break;
default:
break;
}
};
<input onKeyDown={(e) => onKeydown(e.key)} />
上記でinput入力中にエンターキーなど特定のキーを押した際に関数を作動せることができます
しかし、このままでは漢字・予測変換選択中の確定させるためのエンターにも反応して意図しないタイミングで関数が作動します
return()まで(変数・関数宣言)コード
useForm から getValuesメソッドを追加
// React Hook Form を使うための基本設定
const { register, handleSubmit, reset, control, getValues } = useForm({
const {...} = useForm()
の const の後の {} の中に getValues
を追加します
input入力中にバックスペースを押した際の判定に使います
漢字変換・予測変換選択中か否かの判定
// 漢字変換・予測変換(サジェスト)選択中か否かの判定
const [composing, setComposition] = useState(false);
const startComposition = () => setComposition(true);
const endComposition = () => setComposition(false);
そこで上記で変換中か否かの判定を行い、変換を確定させるエンターに反応しないように振り分けます
キーボード操作時の関数
// input入力時にキーボード操作でinput欄を増減
const onKeydown = (e, key, index) => {
const value = getValues(`tasks.${index}.taskValue`);
switch (key) {
// 変換中でない時に エンター で input を増やす
case 'Enter':
e.preventDefault();
if (composing) break;
append({ taskValue: '' });
break;
// input が空欄時に バックスペース で input を減らす
case 'Backspace':
if (index === 0) break;
if (value === "") remove(count);
setCount(count - 1);
break;
default:
break;
}
};
input入力中にエンターを押した際の処理
- input入力中にエンターを押すとデフォルトでは submit(送信)になるので
e.preventDefault();
で阻止 if (composing) break;
は変換中なら、そのまま何も処理を行わない- その後の
append({ valueキー名: 初期値 });break;
で変換中でないなら、append()
メソッドで input を後ろに追加
input入力中にバックスペースを押した際の処理
getValues()
メソッドで input の value(入力内容)を取得(引数は キー名.${index}.valueキー名).if (index === 0) break;
で input を減らしすぎないように1つは残るようにするif (value === "") remove(count);
は value が空欄の時だけremove()
メソッドで input を減らす
return() 内部での <input> のコード解説
<input
{...register(`tasks.${index}.taskValue`)}
onCompositionStart={startComposition}
onCompositionEnd={endComposition}
onKeyDown={(e) => onKeydown(e, e.key, index)}
/>
onCompositionStart={関数名}
で変換”開始“時に作動する関数を指定- 今回は state の composing を true にし、変換中”である“と判定に切り替え
onCompositionEnd={関数名}
で変換”終了“時に作動する関数を指定- 今回は state の composing を false にし、変換中”でない“と判定に切り替え
onKeyDown={(e) => onKeydown(e, e.key, index)}
の引数を(e, e.key, index)
にします
完成コード
サンプルはこちら CodeSandbox(外部サイト)
import { useState } from "react";
import { useForm, useFieldArray } from "react-hook-form";
function Form() {
// React Hook Form を使うための基本設定
const { register, handleSubmit, reset, control, getValues } = useForm({
// input の value の 初期値を設置
defaultValues: {
tasks: [{ taskValue: "" }]
}
});
// input を動的に増減させるための設定
const { fields, prepend, append, remove } = useFieldArray({
control,
name: "tasks"
});
// submitボタンを押した時に行う処理
const onSubmit = (data) => {
console.log(data);
const list = [];
data.tasks.forEach((item, index) =>
list.push(`\nタスク番号${index}:${item.taskValue}`)
);
// 送信後 input の入力欄を初期化
alert(list);
reset();
};
// input をいくつ追加したカウント
const [count, setCount] = useState(0);
const countUp = () => setCount(count + 1);
// input を減らすボタンを押した時の処理
const reduce = () => {
if (count > 0) {
remove(count);
setCount(count - 1);
}
};
// 漢字変換・予測変換(サジェスト)選択中か否かの判定
const [composing, setComposition] = useState(false);
const startComposition = () => setComposition(true);
const endComposition = () => setComposition(false);
const onKeydown = (e, key, index) => {
const value = getValues(`tasks.${index}.taskValue`);
switch (key) {
// 変換中でない時に エンター で input を増やす
case "Enter":
e.preventDefault();
if (composing) break;
append({ taskValue: "" });
break;
// input が空欄時に バックスペース で input を減らす
case "Backspace":
if (index === 0) break;
if (value === "") remove(count);
setCount(count - 1);
break;
default:
break;
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<button
type="button"
onClick={() => [prepend({ taskValue: "" }), countUp()]}
>
前に追加
</button>
{fields.map((field, index) => (
<div key={field.id}>
<label htmlFor={`tasks.${index}.taskValue`}>
タスク番号{index}:
<input
{...register(`tasks.${index}.taskValue`)}
onCompositionStart={startComposition}
onCompositionEnd={endComposition}
onKeyDown={(e) => onKeydown(e, e.key, index)}
/>
</label>
</div>
))}
<button
type="button"
onClick={() => [append({ taskValue: "" }), countUp()]}
>
後ろに追加
</button>
<br />
<button type="button" onClick={reduce}>
減らす
</button>
<br />
<button type="submit">送信</button>
</form>
);
}
export default Form;
コメント