如何在React动态表单中用Zod存储多选框选中的网站URL
解决React中Zod+动态多选框存储URL数组并保留选中状态的问题
核心问题分析
你遇到的两个关键问题:
- 多选框默认绑定布尔值,无法直接存储URL字符串数组
- 用数组索引绑定字段导致切换搜索结果时,新元素覆盖原数组对应位置,丢失之前选中的内容
解决方案
1. 调整字段绑定逻辑:基于URL维护选中数组
放弃用索引(zodSitesUrls.${index})绑定单个数组元素,改为直接操作整个zodSitesUrls数组,通过URL的存在性判断多选框的选中状态,添加/移除URL来更新数组。
2. 具体代码实现
方式一:直接使用useForm的watch和setValue
import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; // 你的Zod验证schema保持不变 const zodValidationSchema = z.object({ zodSitesUrls: z.string() .array() .min(1, { message: "You must choose at least one web site" }) }); export default function YourForm() { const { control, watch, setValue, formState: { errors } } = useForm({ resolver: zodResolver(zodValidationSchema), defaultValues: { zodSitesUrls: [] // 初始化空数组 } }); const selectedUrls = watch('zodSitesUrls'); return ( <div> {/* 你的搜索框部分 */} {webSites?.map((ns) => ( <Checkbox key={ns.siteUrl} // 用唯一URL作为key,避免渲染混乱 label={ns.siteName} checked={selectedUrls.includes(ns.siteUrl)} onChange={(e, isChecked) => { let newUrls; if (isChecked) { // 去重添加,避免重复URL newUrls = [...new Set([...selectedUrls, ns.siteUrl])]; } else { // 移除当前URL newUrls = selectedUrls.filter(url => url !== ns.siteUrl); } setValue('zodSitesUrls', newUrls); }} /> ))} {/* 错误提示 */} {errors.zodSitesUrls && <p>{errors.zodSitesUrls.message}</p>} </div> ); }
方式二:使用Controller绑定整个数组
如果你更倾向于用Controller统一管理字段:
<Controller name="zodSitesUrls" control={control} render={({ field: { value, onChange } }) => ( <> {webSites?.map((ns) => ( <Checkbox key={ns.siteUrl} label={ns.siteName} checked={value.includes(ns.siteUrl)} onChange={(e, isChecked) => { let newValue; if (isChecked) { newValue = [...new Set([...value, ns.siteUrl])]; } else { newValue = value.filter(url => url !== ns.siteUrl); } onChange(newValue); }} /> ))} </> )} />
为什么之前的方法失效?
你之前通过zodSitesUrls.${index}绑定数组的索引位置,当切换搜索关键词后,新的搜索结果数组的索引0对应新的网站,此时操作这个索引会直接覆盖原数组的第一个元素,导致之前选中的体育网站URL丢失。而通过URL唯一标识来维护数组,不管搜索结果怎么变化,都是基于URL的存在性来更新选中状态,不会因为渲染顺序或索引变化丢失数据。
额外注意事项
- 用
ns.siteUrl作为Checkbox的key,确保React正确识别每个多选框的唯一性,避免渲染异常 - 添加去重逻辑(用
Set或者判断!selectedUrls.includes(ns.siteUrl)再添加),防止同一个URL被多次加入数组
内容的提问来源于stack exchange,提问作者andré marquis
相关产品推荐
相关产品推荐

