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

React垂直嵌套列表问题:点击单个州仅展开对应区县子列表

解决React州/区县列表点击单个展开的问题

你当前的核心问题是:所有州组件共用了同一个全局open状态,导致点击任意州时,所有子列表都会同步展开/收起。下面提供两种实用的解决方式,同时修正你代码里的语法和变量名错误。


方案1:每个州组件独立维护展开状态

把展开状态下沉到StateList组件内部,让每个州自己管理是否展开,互不干扰。

修正后的完整代码:

import React, { useState } from "react"

// 区县组件
const AreaList = ({ state }) => {
  return (
    <ul>
      {state.districts.map((district, idx) => (
        <li key={idx}>
          <span className="ml-2 text-outer-space">{district.name}</span>
        </li>
      ))}
    </ul>
  )
}

// 州组件
const StateList = ({ state }) => {
  // 每个州独立的展开状态
  const [isOpen, setIsOpen] = useState(false)
  
  return (
    <div onClick={() => setIsOpen(!isOpen)}>
      <span>{state.name}</span>
      <svg
        viewBox="0 0 24 24"
        className={`${isOpen ? "rotate-180" : ""}`}
      >
        {/* 可添加箭头图标路径,例:<path d="M7 10l5 5 5-5z" /> */}
      </svg>
      {isOpen && <AreaList state={state} />}
    </div>
  )
}

// 父容器组件
const StateDistrictWrapper = ({ states }) => {
  return (
    <div>
      {states.map((state, index) => {
        return <StateList state={state} key={index} />;
      })}
    </div>
  )
}

export default StateDistrictWrapper

方案2:父组件统一管理展开状态

如果需要父组件控制或追踪展开的州,可以在父组件中存储当前展开的州唯一标识(比如ID),子组件根据标识判断是否展开。

修正后的代码:

import React, { useState } from "react"

// 区县组件
const AreaList = ({ state }) => {
  return (
    <ul>
      {state.districts.map((district, idx) => (
        <li key={idx}>
          <span className="ml-2 text-outer-space">{district.name}</span>
        </li>
      ))}
    </ul>
  )
}

// 州组件
const StateList = ({ state, expandedStateId, setExpandedStateId }) => {
  const isOpen = expandedStateId === state.id // 假设每个州有唯一id字段
  
  const toggleOpen = () => {
    // 点击时切换:已展开则收起,未展开则展开当前州
    setExpandedStateId(expandedStateId === state.id ? null : state.id)
  }
  
  return (
    <div onClick={toggleOpen}>
      <span>{state.name}</span>
      <svg
        viewBox="0 0 24 24"
        className={`${isOpen ? "rotate-180" : ""}`}
      >
        {/* 可添加箭头图标路径 */}
      </svg>
      {isOpen && <AreaList state={state} />}
    </div>
  )
}

// 父容器组件
const StateDistrictWrapper = ({ states }) => {
  // 存储当前展开的州id,初始为null(全部收起)
  const [expandedStateId, setExpandedStateId] = useState(null)
  
  return (
    <div>
      {states.map((state, index) => {
        return (
          <StateList 
            state={state} 
            key={index} 
            expandedStateId={expandedStateId}
            setExpandedStateId={setExpandedStateId}
          />
        );
      })}
    </div>
  )
}

export default StateDistrictWrapper

原代码的额外错误修正

  1. 变量名混淆:states.map((city, index) 里的city建议改为state,避免和子组件props冲突;原代码中StateList state={state}实际应为state={city}(若保留city变量名)
  2. 语法错误:Const需改为小写const,[open,,setOpen]多余的逗号要删除
  3. Props传递错误:AreaList area={city}应改为state={city},匹配AreaList接收的参数
  4. 标签不闭合:原代码中存在多余的</h2>和未闭合标签,需修正

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:36:06