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
相关产品推荐
相关产品推荐

