如何在React中根据另一个下拉框动态改变下拉选项?
解决方案
要实现切换type下拉框时更新table_id的选项,核心是在type状态变化时触发接口请求,再用返回的数据更新菜单选项,具体步骤如下:
1. 监听type变化触发请求
修改原有的useEffect,将type加入依赖数组,这样每次type改变时都会重新执行请求逻辑:
const [menus, setMenus] = useState([]); useEffect(() => { // 未选择type时不发起请求 if (!type) return; async function fetchMenusByType() { try { // 调用根据type筛选菜单的接口(需确保menuservice提供此方法,或调整getAll接口支持传参) const result = await menuservice.getByType(type); setMenus(result.data); // 重置table_id,避免选中的id不在新选项中导致异常 setTable_id(0); } catch (error) { console.error('加载菜单数据失败:', error); } } fetchMenusByType(); }, [type]); // 依赖type,状态变化时重新执行
如果你的getAll接口支持通过查询参数过滤类型,也可以改成:
const result = await menuservice.getAll({ type: type });
2. 优化下拉框渲染逻辑
在table_id的下拉框中,只有当menus有数据时才渲染选项,同时修正原代码中link输入框的id错误(原代码写的是name,会和第一个输入框冲突):
<select name="table_id" className="input" value={table_id} onChange={(e) => setTable_id(e.target.value)} > <option disabled>--Chọn menu cha--</option> <option value="0">Không có cha</option> {menus.map((menu) => ( <option key={menu.id} value={menu.id}> {menu.name} </option> ))} </select>
完整修改后的组件代码
import { faBackward, faFloppyDisk } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link, useNavigate } from "react-router-dom"; import { useEffect, useState } from "react"; import menuservice from "../../../services/MenuService"; function MenuCreate() { const navigate = useNavigate(); const [name, setName] = useState(""); const [link, setLink] = useState(""); const [table_id, setTable_id] = useState(0); const [type, setType] = useState(""); const [status, setStatus] = useState(1); const [menus, setMenus] = useState([]); async function postStore(event) { event.preventDefault(); const image = document.querySelector("#image"); var menu = new FormData(); menu.append("name", name); menu.append("link", link); menu.append("table_id", table_id); menu.append("type", type); menu.append("status", status); menu.append("image", image.files[0]); try { const res = await menuservice.create(menu); alert(res.data.message); navigate("../../admin/menu", { replace: true }); } catch (error) { console.error(error.response.data); } } useEffect(() => { if (!type) return; async function fetchMenusByType() { try { // 替换为你的实际接口调用逻辑 const result = await menuservice.getByType(type); setMenus(result.data); setTable_id(0); } catch (error) { console.error('加载菜单数据失败:', error); } } fetchMenusByType(); }, [type]); return ( <section className="mainList"> <div className="wrapper"> <div className="card1"> <form method="post" onSubmit={postStore}> <div className="card-header"> <strong className="title1">THÊM MENU</strong> <div className="button"> <Link to="/admin/menu" className="backward"> <FontAwesomeIcon icon={faBackward} /> Go back </Link> <button type="submit" className="save"> <FontAwesomeIcon icon={faFloppyDisk} /> Save </button> </div> </div> <div className="form-container grid -bottom-3 "> <div className="grid__item large--three-quarters"> <fieldset className="input-container"> <label htmlFor="name">Tên menu</label> <input name="name" type="text" className="input" id="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="Nhập tên menu..." /> </fieldset> <fieldset className="input-container"> <label htmlFor="link">Đường dẫn menu</label> <input name="link" type="text" className="input" id="link" value={link} onChange={(e) => setLink(e.target.value)} placeholder="Nhập đường dẫn..." /> </fieldset> </div> <div className="grid__item large--one-quarter"> <fieldset className="input-container"> <label htmlFor="type">Chọn loại menu</label> <select name="type" className="input" value={type} onChange={(e) => setType(e.target.value)} > <option value="">--Chọn loại menu--</option> <option value="mainmenu">Menu chính</option> <option value="footermenu">Menu footer</option> </select> </fieldset> <fieldset className="input-container"> <label htmlFor="table_id">Chọn menu cha</label> <select name="table_id" className="input" value={table_id} onChange={(e) => setTable_id(e.target.value)} > <option disabled>--Chọn menu cha--</option> <option value="0">Không có cha</option> {menus.map((menu) => ( <option key={menu.id} value={menu.id}> {menu.name} </option> ))} </select> </fieldset> <fieldset className="input-container"> <label htmlFor="status">Tình trạng xuất bản</label> <select name="status" className="input" value={status} onChange={(e) => setStatus(e.target.value)} > <option disabled>--Chọn tình trạng xuất bản--</option> <option value="1">Xuất bản</option> <option value="2">Không xuất bản</option> </select> </fieldset> </div> </div> </form> </div> </div> </section> ); } export default MenuCreate;
额外提示
- 如果
menuservice没有提供按类型查询的方法,需要先在后端实现对应接口,再在前端封装调用逻辑 - 可以添加加载状态(比如请求时显示加载动画),提升用户体验
内容的提问来源于stack exchange,提问作者Alukusukuku
相关产品推荐
相关产品推荐

