アンケートアプリの作成の作成中、質問の回答結果によって次の質問が表示される動作を実装するのに苦戦したので書き留めておきます。
##実装したいこと
Q1もしくはQ2の回答でラジオボタンの「はい」を選択した場合のみ、Q3が表示されるようにしたい。どちらの問いにも「いいえ」と「わからない」を選択した時は何も変化しない。
##結果
react-hook-formの'watch'を使うことで、ラジオボタンの選択した結果を条件に定義することができ、実装することができた。
https://react-hook-form.com/jp/api#watch
まずは、ラジオボタンの選択結果を変数に入れる。
export default function Home() {
const {
register,
watch,
handleSubmit,
formState: { errors },
control
} = useForm()
const watchIsLearning = watch("isLearning");
const watchWasLearning = watch("wasLearning");
次にその変数を使って条件分岐し、決められた条件の場合に動作が起こるようにする。
{ ( watchIsLearning === "true" || watchWasLearning === "true" ) &&
条件付きレンダリングとして論理 && 演算子を用いることが多いそう。
今回は2つの質問のどちらかがtrueであれば良いので、or ( || )を使った。
その場合は || と && では && の方が優先して実行されるようなので、()を使用して || を優先するように書いたところ成功した。
##全体コード
import { useForm, Controller } from 'react-hook-form';
import { Container, Input, TextField } from "@material-ui/core";
export default function Home() {
const {
register,
watch,
handleSubmit,
formState: { errors },
control
} = useForm()
const watchIsLearning = watch("isLearning");
const watchWasLearning = watch("wasLearning");
return (
<>
<Container>
<h1>プログラミング学習に関するアンケート</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<span>Q1.現在、プログラミング学習をしていますか?</span>
<input id="isLearning1" {...register("isLearning", { required: true })}
name="isLearning"
type="radio"
value="true"
/>
<label htmlFor="isLearning1">はい</label>
<input id="isLearning2" {...register("isLearning", { required: true })}
name="isLearning"
type="radio"
value="false"
/>
<label htmlFor="isLearning2">いいえ</label>
<input id="isLearning3" {...register("isLearning", { required: true })}
name="isLearning"
type="radio"
value="null"
/>
<label htmlFor="isLearning3">わからない</label>
{
errors.isLearning &&
<span>このフィールドは回答必須です。</span>
}
</div>
<div>
<span>Q2.これまでに、プログラミングを学習したことがありますか?</span>
<input id="wasLearning1" {...register("wasLearning", { required: true })}
name="wasLearning"
type="radio"
value="true"
/>
<label htmlFor="wasLearning1">はい</label>
<input id="wasLearning2" {...register("wasLearning", { required: true })}
name="wasLearning"
type="radio"
value="false"
/>
<label htmlFor="wasLearning2">いいえ</label>
<input id="wasLearning3" {...register("wasLearning", { required: true })}
name="wasLearning"
type="radio"
value="null"
/>
<label htmlFor="wasLearning3">わからない</label>
{
errors.wasLearning &&
<span>このフィールドは回答必須です。</span>
}
</div>
{ ( watchIsLearning === "true" || watchWasLearning === "true" ) &&
<div>
<label htmlFor="learningLanguage">Q3.これまで学習したことのあるプログラミング言語をすべて教えてください。</label>
<Controller
name="learningLanguage"
defaultValue=""
control={control}
render={({ field: { value, onChange } }) => (
<TextField
value={value}
onChange={onChange}
fullWidth
margin="normal"
rows={3}
multiline
variant="outlined"
/>
)}
/>
</div>
}
<input type="submit" value="アンケートを提出する" />
</form>
</Container>
</>
)
}