You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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>
    );
}

关键改动说明

  1. 移除独立状态变量:不再用useState单独管理会议、分区状态,完全依赖React-Hook-Form统一管理表单状态
  2. 实时监听字段变化:通过watch('conference')获取当前选中的会议,动态过滤对应的分区列表
  3. 联动更新字段:在分区选择的onChange事件中,先更新分区字段,再通过setValue自动设置对应的会议
  4. 统一初始值:在useForm的defaultValues中设置关联的初始值,保证初始状态的一致性

内容的提问来源于stack exchange,提问作者190303458

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:00:58