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

ReactJS实现手风琴式兄弟元素内容单点击切换显示/隐藏功能

实现React手风琴(Accordion)效果解决方案

你的问题很典型——当每个子组件独立维护状态时,没法实现兄弟组件间的联动(展开一个、收起其他)。我们需要把状态提升到父组件统一管理,这样就能完美复刻你想要的手风琴效果了。

修改思路

  1. 在父组件App中维护一个activeCity状态,用来记录当前被选中的城市名称
  2. 给每个Toggle组件传递当前激活的城市名,以及点击时触发的回调函数
  3. 子组件Toggle不再维护自己的toggle状态,而是通过父组件传递的activeCity来判断是否显示内容

修改后的代码

App.js

import { useState } from 'react';
import Toggle from './components/Toggle';

const cities = [
 { name: "Mysuru", about: "Mysore (or Mysuru), a city in India's southwestern Karnataka state, was the capital of the Kingdom of Mysore from 1399 to 1947. In its center is opulent Mysore Palace, seat of the former ruling Wodeyar dynasty." },
 { name: "Bengaluru", about: "Bengaluru (also called Bangalore) is the capital of India's southern Karnataka state. The center of India's high-tech industry, the city is also known for its parks and nightlife. By Cubbon Park, Vidhana Soudha is a Neo-Dravidian legislative building." },
 { name: "Udupi", about: "Udupi is a city in the southwest Indian state of Karnataka. It's known for its Hindu temples, including the huge, 13th-century Sri Krishna Temple, which houses a statue of Lord Krishna and attracts many pilgrims." },
 { name: "Mandya", about: "Mandya is a city in the state of Karnataka. It is the headquarter of Mandya district and is located 45 kilometres from Mysore and 100 kilometres from Bangalore" },
 { name: "Kodagu", about: "Kodagu, also known as Coorg, is a rural district in the southwest Indian state of Karnataka. In the area’s north, Madikeri Fort has 2 life-size elephant statues at its entrance, plus a Gothic-style church with a museum on its grounds." }
];

function App() {
 // 维护当前激活的城市名称,初始为null(全部收起)
 const [activeCity, setActiveCity] = useState(null);

 // 处理城市点击事件:如果点击的是当前激活的城市,就收起;否则切换到该城市
 const handleCityClick = (cityName) => {
  setActiveCity(prev => prev === cityName ? null : cityName);
 };

 return (
  <div className="App">
   <div className="toggle-container">
    <div className="cities">
     {cities.map((city) => (
      <Toggle 
       key={city.name} 
       city={city} 
       isActive={activeCity === city.name}
       onClick={() => handleCityClick(city.name)}
      />
     ))}
    </div>
   </div>
  </div>
 );
}

export default App;

Toggle.js

// 移除子组件自己的state,完全由父组件控制状态
export default function Toggle({ city, isActive, onClick }) {
 return (
  <>
   <p className="city-name" onClick={onClick}>
    {city.name}
    {/* 可选:添加箭头图标增强交互提示 {isActive ? " ▼" : " ▶"} */}
   </p>
   <p className={isActive ? "city-about-show" : "city-about-hide"}>
    {city.about}
   </p>
  </>
 );
}

style.css(可选动画优化)

如果想要更顺滑的展开收起动画,可以把display: none改成max-height过渡(display切换无法添加动画),替换这两个类:

.city-about-hide{
 max-height: 0;
 overflow: hidden;
 transition: max-height 0.3s ease-out;
 padding: 0 15px;
}
.city-about-show {
 max-height: 200px; /* 可根据内容高度调整 */
 overflow: hidden;
 transition: max-height 0.3s ease-in;
 font-family: sans-serif;
 color: rgb(105, 105, 105);
 background-color: rgb(214, 231, 247);
 letter-spacing: 0.3px;
 font-size: 14px;
 padding: 20px 15px;
 line-height: 1.5;
}

效果说明

现在点击任意城市名称:

  • 如果该城市未展开:会展开它的内容,同时自动收起其他所有城市的内容
  • 如果该城市已经展开:会收起它的内容(保持全部收起状态)

这样就完全实现了你参考的GIF里的手风琴交互效果啦!

内容的提问来源于stack exchange,提问作者Manoj L Nayak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:27:44