React表单中统计Yes/No答案并存入数组的实现方法
实现选中Yes时向数组添加元素的方案
从你的代码来看,你应该是用react-hook-form处理表单逻辑(用到了register方法),下面分步骤实现需求:
1. 初始化状态数组
首先在组件顶部用React的useState钩子初始化questionAns数组,用来存储选中的"Yes"回答:
import { useState } from 'react'; // ... 其他Material UI和react-hook-form的导入 export default function YourFormComponent() { // 初始化空数组存储Yes回答 const [questionAns, setQuestionAns] = useState([]); // 初始化react-hook-form(如果还没写的话) const { register, errors, watch } = useForm(); // ... 其他逻辑和渲染代码 }
2. 监听单选框选择并更新数组
有两种简单的方式实现监听,选一种适合你的即可:
方式一:给RadioGroup绑定onChange事件
直接给RadioGroup添加回调函数,当选中值变化时判断是否为"Yes",再更新数组:
<FormControl error={Boolean(errors.question1)}> <FormLabel component="legend"> {Records[0].question} </FormLabel> <RadioGroup row aria-label="question1" name="question1" onChange={(e) => { const selectedValue = e.target.value; if (selectedValue === "Yes") { // 注意:必须创建新数组,不能直接修改原数组 setQuestionAns(prev => [...prev, 'yes']); } else { // 可选:如果需要取消选择Yes时移除对应元素,可添加以下代码 // setQuestionAns(prev => prev.filter(item => item !== 'yes')); } }} > <FormControlLabel value="Yes" control={ <Radio {...register("awQuestion1", { required: "Please select a response.", })} /> } label="Yes" /> <FormControlLabel value="No" control={ <Radio {...register("awQuestion1", { required: "Please select a response.", })} /> } label="No" /> </RadioGroup> <FormHelperText style={{ color: "#d32f2f" }}> {errors.question1?.message} </FormHelperText> </FormControl>
方式二:用react-hook-form的watch监听字段变化
通过watch函数监听单选框字段的变化,结合useEffect处理数组更新:
import { useEffect } from 'react'; import { useForm, watch } from 'react-hook-form'; export default function YourFormComponent() { const [questionAns, setQuestionAns] = useState([]); const { register, errors } = useForm(); // 监听awQuestion1字段的实时值 const selectedValue = watch('awQuestion1'); // 当选中值变化时触发逻辑 useEffect(() => { if (selectedValue === "Yes") { setQuestionAns(prev => [...prev, 'yes']); } else { // 可选:取消选择Yes时移除对应元素 // setQuestionAns(prev => prev.filter(item => item !== 'yes')); } }, [selectedValue]); // 依赖选中值,值变化时执行 // ... 渲染表单的代码 }
3. 处理多个结构相同的问题
如果有大量相同结构的Yes/No问题,最好封装成可复用组件,避免重复代码:
第一步:创建复用的YesNoQuestion组件
// YesNoQuestion.jsx import React from 'react'; import { FormControl, FormLabel, RadioGroup, FormControlLabel, Radio, FormHelperText } from '@mui/material'; import { useFormContext } from 'react-hook-form'; export default function YesNoQuestion({ questionText, fieldKey, error, onYesSelect }) { const { register } = useFormContext(); // 借助FormContext共享表单方法 return ( <FormControl error={Boolean(error)}> <FormLabel component="legend">{questionText}</FormLabel> <RadioGroup row aria-label={fieldKey} name={fieldKey} onChange={(e) => { if (e.target.value === "Yes") { onYesSelect(); // 触发父组件的数组更新逻辑 } }} > <FormControlLabel value="Yes" control={<Radio {...register(fieldKey, { required: "Please select a response." })} />} label="Yes" /> <FormControlLabel value="No" control={<Radio {...register(fieldKey, { required: "Please select a response." })} />} label="No" /> </RadioGroup> <FormHelperText style={{ color: "#d32f2f" }}> {error?.message} </FormHelperText> </FormControl> ); }
第二步:在父组件中批量使用该组件
// 父组件 import YesNoQuestion from './YesNoQuestion'; import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; export default function YourForm() { const [questionAns, setQuestionAns] = useState([]); const methods = useForm(); const { errors } = methods; const handleYesSelect = () => { setQuestionAns(prev => [...prev, 'yes']); }; return ( <FormProvider {...methods}> {/* 第一个问题 */} <YesNoQuestion questionText={Records[0].question} fieldKey="awQuestion1" error={errors.awQuestion1} onYesSelect={handleYesSelect} /> {/* 第二个问题 */} <YesNoQuestion questionText={Records[1].question} fieldKey="awQuestion2" error={errors.awQuestion2} onYesSelect={handleYesSelect} /> {/* 更多问题直接复制上述代码,修改对应参数即可 */} </FormProvider> ); }
额外提示
如果需要区分是哪个问题的Yes回答,可以修改handleYesSelect,传递问题标识,比如往数组中存入{questionId: 1, answer: 'yes'}这类对象,方便后续对具体问题的回答做处理。
内容的提问来源于stack exchange,提问作者user318369
相关产品推荐
相关产品推荐

