假设目标是使所有选择保持相同group
字段,它必须是一个按提供的顺序记录所选值的数组,如果指定,则将自定义输入值作为最后一项,也许理想情况下,计算中的值会更容易onSubmit
提交之前。
但由于偏好不添加逻辑onSubmit
,也许另一种选择是托管本地状态,在状态发生变化时运行所需的计算,然后调用setValue
手动将计算值同步到group
field.
经过修改的分叉演示:代码沙箱
import "./styles.css";
import { Controller, useFormContext } from "react-hook-form";
import React, { useState, useEffect } from "react";
export const Component = ({ name, ITEMS }) => {
const { control, setValue } = useFormContext();
const [state, setState] = useState({});
useEffect(() => {
const { custom, ...items } = state;
const newItems = Object.entries(items).filter((item) => !!item[1]);
newItems.sort((a, b) => a[0] - b[0]);
const newValues = newItems.map((item) => item[1]);
if (custom) {
setValue(name, [...newValues, custom]);
return;
}
setValue(name, [...newValues]);
}, [name, state, setValue]);
const handleCheck = (val, idx) => {
setState((prev) =>
prev[idx] ? { ...prev, [idx]: null } : { ...prev, [idx]: val }
);
};
const handleCheckCustom = (checked) =>
setState((prev) =>
checked ? { ...prev, custom: "" } : { ...prev, custom: null }
);
const handleInputChange = (e) => {
setState((prev) => ({ ...prev, custom: e.target.value }));
};
return (
<Controller
name={name}
control={control}
render={({ field, formState }) => {
return (
<>
{ITEMS.map((item, index) => {
const isCustomField = index === ITEMS.length - 1;
return (
<React.Fragment key={index}>
<label>
{item.id}
<input
type="checkbox"
name={name}
onChange={(e) =>
isCustomField
? handleCheckCustom(e.target.checked)
: handleCheck(e.target.value, index)
}
value={item.value}
/>
</label>
{typeof state["custom"] === "string" && isCustomField && (
<input onChange={handleInputChange} type="text" />
)}
</React.Fragment>
);
})}
</>
);
}}
/>
);
};