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

React v18实现依赖级联select字段选项自动选中的方法

React 18 关联选择框实现方案

问题根因

你遇到的两个问题本质是同一个原因:没有将三个select做成受控组件,既没有存储各字段的当前选中值,也没有将select的选中状态和组件状态绑定:

  • 没有全局存储选中值,选产品的时候自然拿不到当前已选的分类值
  • 没有给select绑定value属性,哪怕拿到了需要选中的值,组件也不会自动切换选中项

具体修改步骤

  1. 新增3个状态,分别存储三个选择框的当前选中值
  2. 给每个<select>标签绑定value属性,关联对应状态,实现状态和选中项的双向绑定——只要更新状态值,select会自动选中对应value的option,不需要手动操作DOM
  3. 调整各个选择事件的逻辑:
    • 选中分类时:更新分类选中状态,拉取对应分类的产品列表,同时清空已选的产品和ID,避免出现跨分类的无效值
    • 选中ID时:拉取对应详情,拿到分类和产品信息后更新三个选中状态,同时同步刷新对应分类下的产品列表
    • 选中产品时:直接从状态里读取当前已选的分类值,和产品值一起传给接口查对应ID,拿到ID后更新ID选中状态
  4. (可选)之前react-select不生效是因为它要求选项格式为{value: 选项值, label: 显示文本},把接口返回的原始列表按这个格式转一下就能正常用。

修改后完整代码

--------------------------------
         dselect.js 
--------------------------------
import {Row, Col, Container} from "react-bootstrap"
import React, { useState, useEffect } from 'react';
const baseurl = "http://localhost:5000/api";
const Dselect=()=>{
     // 列表类状态
     const [catList, setCatList] = useState([]);
     const [pdtList, setPdtlist] = useState([]);
     // 选中值状态,核心用于受控绑定和跨字段取值
     const [selectedId, setSelectedId] = useState("");
     const [selectedCategory, setSelectedCategory] = useState("");
     const [selectedProduct, setSelectedProduct] = useState("");

     // 初始化拉取分类和全量产品列表
     useEffect(()=>{
          const fetchCat = async() => {
               const res = await fetch(`${baseurl}/cat`);
               const cList = await res.json();
               setCatList(cList)
          }         

          const fetchAllPdt = async() => {
               const res = await fetch(`${baseurl}/pdtlist`);
               const pList = await res.json();
               setPdtlist(pList)
          }

          fetchCat();
          fetchAllPdt();
     },[])

     // 选中ID时联动分类和产品
     const getPdtDetails = async(e) => {
          const pdtID = e.target.value;
          setSelectedId(pdtID);
          // 选空值时重置其他选项
          if(!pdtID) {
               setSelectedCategory("");
               setSelectedProduct("");
               const res = await fetch(`${baseurl}/pdtlist`);
               const pList = await res.json();
               setPdtlist(pList);
               return;
          }
          const res = await fetch(`${baseurl}/details`,{
               method: "POST",
               headers: { "Content-Type": "application/json" },
               body: JSON.stringify({data:pdtID}),  
          });
          const detList = await res.json();
          // 更新分类和产品的选中状态,select会自动选中对应项
          setSelectedCategory(detList.category);
          setSelectedProduct(detList.pdt_id);
          // 同步拉取对应分类下的产品列表
          const pdtRes = await fetch(`${baseurl}/pdtList`,{
               method: "POST",
               headers: { "Content-Type": "application/json" },
               body: JSON.stringify({data:detList.category}),  
          });
          const catPdtList = await pdtRes.json();
          setPdtlist(catPdtList);
     } 
     
     // 选中分类时筛选对应产品
     const updateList = async(e) =>{
          const catVal = e.target.value;
          setSelectedCategory(catVal);
          // 切换分类时清空已选的产品和ID,避免无效值
          setSelectedProduct("");
          setSelectedId("");
          if(!catVal) {
               // 选空分类时恢复全量产品列表
               const res = await fetch(`${baseurl}/pdtlist`);
               const pList = await res.json();
               setPdtlist(pList);
               return;
          }
          const res = await fetch(`${baseurl}/pdtList`,{
                    method: "POST",
                    headers: { "Content-Type": "application/json" },
                    body: JSON.stringify({data:catVal}),  
          });
          const catPdtList = await res.json();
          setPdtlist(catPdtList)
     }

     // 选中产品时联动ID
     const getPdtcode = async(e) =>{
          const pdtVal = e.target.value;
          setSelectedProduct(pdtVal);
          if(!pdtVal) {
               setSelectedId("");
               return;
          }
          // 直接从状态取当前选中的分类值,不需要从事件对象获取
          const currentCat = selectedCategory;
          const res = await fetch(`${baseurl}/pdtCode`,{
                    method: "POST",
                    headers: { "Content-Type": "application/json" },
                    body: JSON.stringify({
                         pdtId: pdtVal,
                         category: currentCat
                    }),  
          });
          const code = await res.json();
          // 更新ID选中状态,自动选中对应项
          setSelectedId(code.pdt_id);
     }

    return(
     <div>
          <Container className="m-5">
               <Row>
                    <Col lg={4} md={4} xs={6}>
                         <label>ID</label>
                         {/* 绑定value到对应状态,实现受控 */}
                         <select name="product_id" value={selectedId} onChange={getPdtDetails} >
                         <option value="">-</option>
                              {pdtList.map((item) =>(
                                   <option key={item.pdt_id} value={item.pdt_id}> {item.pdt_id} </option>
                              ))}
                         </select>
                    </Col>

                    <Col lg={4} md={4} xs={6}> <label>Category</label>                             
                         <select name="category" value={selectedCategory} onChange={updateList}  >
                              <option value="">-</option>
                              {catList.map((item) =>(
                                   <option key={item.cat_id} value={item.category}>{item.category}</option>
                              ))}
                         </select>                              
                    </Col>
                    <Col lg={4} md={4} xs={6}> <label>Product </label>
                        <select name="product" value={selectedProduct} onChange={getPdtcode} >
                         <option value="">-</option>
                              {pdtList.map((item) =>(
                                   <option key={item.pdt_id} value={item.pdt_id}> {item.pdt_name} </option>
                              ))}
                         </select>                     
                    </Col>
               </Row>
          </Container>
     </div>
    )    
}
  
export default Dselect

补充说明

如果后续要换回react-select,只需要把传入的options做格式转换即可,示例:

import Select from "react-select";

// 组件内使用示例
<Select 
  options={pdtList.map(item => ({
    value: item.pdt_id,
    label: item.pdt_name
  }))}
  value={selectedProduct ? {
    value: selectedProduct, 
    label: pdtList.find(i => i.pdt_id === selectedProduct)?.pdt_name
  } : null}
  onChange={(opt) => {
    // 选中逻辑和原生select一致,取opt.value做后续处理即可
  }}
  placeholder="Select product" 
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:27:18