如何用React-Hook-Form实现两个关联MUI Select字段的联动控制?
React-Hook-Form结合MUI实现关联Select组件
需求说明
需要实现两个MUI Select组件的关联逻辑:
- 选中
division(分区)时,自动选中其对应的conference(会议) - 选中
conference时,division列表自动过滤为该会议下的所有分区
数据源
const teams = [ { "conference": "Eastern", "division": "Atlantic" }, { "conference": "Eastern", "division": "Central" }, { "conference": "Eastern", "division": "Southeast" }, { "conference": "Western", "division": "Northwest" }, { "conference": "Western", "division": "Pacific" }, { "conference": "Western", "division": "Southwest" } ]
问题分析
你当前的代码混用了React-Hook-Form和独立的useState管理状态,导致表单状态不同步。正确的做法是让React-Hook-Form统一管理所有表单字段,通过watch和setValue实现字段间的联动。
解决方案代码
import { useForm, Controller } from 'react-hook-form'; import { Grid, Typography, Select, MenuItem } from '@mui/material'; const teams = [ { "conference": "Eastern", "division": "Atlantic" }, { "conference": "Eastern", "division": "Central" }, { "conference": "Eastern", "division": "Southeast" }, { "conference": "Western", "division": "Northwest" }, { "conference": "Western", "division": "Pacific" }, { "conference": "Western", "division": "Southwest" } ]; export default function Demo() { const { control, watch, setValue } = useForm({ defaultValues: { conference: "Western", division: "Pacific" } }); // 实时监听当前选中的会议 const currentConference = watch('conference'); // 过滤当前会议对应的分区列表 const filteredDivisions = teams .filter(item => item.conference === currentConference) .map(item => item.division); // 获取所有唯一会议选项 const uniqueConferences = [...new Set(teams.map(item => item.conference))]; return ( <form> <Grid container columnSpacing={4}> <Grid xs={6}> <Typography sx={{ fontWeight: "bold" }}>Conference</Typography> <Controller name='conference' control={control} render={({ field }) => ( <Select {...field} fullWidth > {uniqueConferences.map((conf, index) => ( <MenuItem key={index} value={conf}>{conf}</MenuItem> ))} </Select> )} /> </Grid> <Grid xs={6}> <Typography sx={{ fontWeight: "bold" }}>Division</Typography> <Controller name='division' control={control} render={({ field }) => ( <Select {...field} fullWidth displayEmpty renderValue={selected => selected?.length === 0 ? <span>-- Select --</span> : selected} onChange={(e) => { // 更新分区字段 field.onChange(e); // 根据选中分区自动匹配并更新会议字段 const matchedConference = teams.find(item => item.division === e.target.value)?.conference; if (matchedConference) { setValue('conference', matchedConference); } }} > {filteredDivisions.map((div, index) => ( <MenuItem key={index} value={div}>{div}</MenuItem> ))} </Select> )} /> </Grid> </Grid> </form> ); }
关键改动说明
- 移除独立状态变量:不再用
useState单独管理会议、分区状态,完全依赖React-Hook-Form统一管理表单状态 - 实时监听字段变化:通过
watch('conference')获取当前选中的会议,动态过滤对应的分区列表 - 联动更新字段:在分区选择的
onChange事件中,先更新分区字段,再通过setValue自动设置对应的会议 - 统一初始值:在
useForm的defaultValues中设置关联的初始值,保证初始状态的一致性
内容的提问来源于stack exchange,提问作者190303458
相关产品推荐
相关产品推荐

