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

React使用fetch实现选择州后动态填充Material-UI城市下拉菜单问题求助

问题核心原因
  • 你的fetchData是async异步函数,返回值是Promise对象而非直接返回城市数组,直接将Promise存入cities状态会导致无法渲染下拉选项
  • MUI的Select属于受控组件,必须绑定value属性对应状态值,否则选中状态无法正常显示
  • 存储选中州的State状态初始值配置错误,选中值为单个字符串,初始值应设为空字符串而非空数组
  • 原代码中MenuItem标签前多了空格,属于语法错误会导致渲染异常
修正后的完整代码
import React from 'react';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import {Select, MenuItem} from '@material-ui/core';

import './App.css';

export function getStates() {
    return [
        {name: 'California', id: "1"},
        {name: 'New York', id: "2"},
    ]
}

function Home() {
    const useStyles = makeStyles((theme: Theme) =>
        createStyles({
            formControl: {
                margin: theme.spacing(1),
                minWidth: 120,
            },
            selectEmpty: {
                marginTop: theme.spacing(2),
            },
        }),
    );

    // 修正初始值,选中的州是字符串类型
    const [selectedState, setSelectedState] = React.useState('');
    const [cities, setCities] = React.useState([]);

    const selectStyle = makeStyles(theme => ({
        root: {
            textDecoration: 'none',
            color: 'red',
            alignItems: 'center',
            fontWeight: "bold",
            display: "flex",
            justifyContent: "space-around",
            fontSize: 18,
            margin: 0,
            '&:hover': {
                textDecoration: 'none'
            }
        },
    }));

    // 改为异步事件处理函数
    const handleStateChange = async (event: React.ChangeEvent<{ value: unknown }>) => {
        const stateVal = event.target.value as string;
        setSelectedState(stateVal);
        // 选择州后清空原有城市
        setCities([]);
        
        try {
            // 请求body填入选中的州信息,这里按你的实际接口要求调整
            const reqBody = JSON.stringify({state: stateVal})
            const res = await fetch('http://127.0.0.1:8080', 
                {
                    method : "POST",
                    headers: {"content-type": "application/json"}, // 接口如果是text/plain可以改回去
                    body: reqBody
                }
            );
            const data = await res.json();
            const cityList = [];
            for(let key in data.cities) {
                cityList.push({id: key, name: data.cities[key]})
            }
            // 拿到结果后更新城市状态
            setCities(cityList);
        }
        catch (err) {
            console.log("请求城市列表异常: " + err)
        }
    }

    const fixed_states = getStates();
    const classes = useStyles()
    const selectClass = selectStyle()

    return (
        <div className="main-select">
        <container>
        <FormControl required className={classes.formControl}>
        <InputLabel id="state_select_labelid">State</InputLabel>
        {/* 新增value属性绑定选中值 */}
        <Select 
            labelId="state_select_labelid" 
            id="state_select_id" 
            name="state_select_name" 
            value={selectedState}
            onChange={handleStateChange} 
            className={selectClass.root}
        >
        {fixed_states.map(({id, name}) => (
            <MenuItem key={id} value={name}>
                {name}
            </MenuItem>
        )) }
        </Select>
        <FormHelperText></FormHelperText>
      </FormControl>

        <FormControl required className={classes.formControl}>
        <InputLabel id="city_input_label_id">City</InputLabel>
        {/* 新增value属性,后续需要存储选中城市可以单独加状态绑定 */}
        <Select 
            labelId="city_select_labelid" 
            id="city_select_id" 
            name="city_select_name"
            value={''}
        >
        {cities.map(({id, name}) => (
            <MenuItem key={id} value={name}>
                {name}
            </MenuItem>
        ))}

        </Select>
        <FormHelperText></FormHelperText>
      </FormControl>

        </container>
        </div>
    );
}

export default Home;

如果你的接口要求请求头是text/plain,可以自行把请求头里的content-type改回原来的配置,请求body也按你的接口要求调整即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:57:05