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

React中如何实现点击仅展开对应问答项,其余保持隐藏

解决React FAQ组件独立展开收起问题

你的问题核心是所有问答项共用了全局的toggle和rotateArrow状态,导致一点击就全展开/收起。要实现独立控制,只需要用一个状态记录当前展开的项ID,让每个项根据自身ID判断是否显示即可。

具体实现步骤

  1. 把FAQ数据整理成数组,方便批量渲染和后续扩展
  2. 用expandedId状态记录当前展开的项ID(初始为null,表示全部收起)
  3. 点击箭头时切换expandedId:如果当前项已经展开就收起,否则展开该项
  4. 每个项的箭头旋转、答案显示都依赖自身ID与expandedId的匹配关系

重构后的代码

import { useState } from 'react';

function FAQs() {
    // 整理FAQ数据,每个项带唯一id、问题、答案
    const faqData = [
        {
            id: 1,
            question: "First question goes here",
            answer: "Question 1 Answer, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat zzril delenit augue duis dolore te feugait nulla facilisi."
        },
        {
            id: 2,
            question: "Second question goes here",
            answer: "Question 2 Answer, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat zzril delenit augue duis dolore te feugait nulla facilisi."
        }
    ];

    // 记录当前展开的项ID,初始为null(全部收起)
    const [expandedId, setExpandedId] = useState(null);

    // 点击箭头的处理函数:切换当前展开项
    const handleToggle = (id) => {
        setExpandedId(prevId => prevId === id ? null : id);
    };

    return (
        <div>
            {faqData.map(item => (
                <div key={item.id} style={{ marginBottom: '16px' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                        <Question>{item.question}</Question>
                        <ArrowRight 
                            onClick={() => handleToggle(item.id)}
                            style={{ 
                                transform: expandedId === item.id ? "rotate(90deg)" : "rotate(0)",
                                transition: 'transform 0.3s ease' // 加个过渡动画更自然
                            }}
                        />
                    </div>
                    {/* 只有当前项ID匹配时才显示答案 */}
                    {expandedId === item.id && (
                        <Answer>
                            <p>{item.answer}</p>
                        </Answer>
                    )}
                </div>
            ))}
        </div>
    );
}

// 假设这些是你已定义的组件
const Question = ({ children }) => <h3>{children}</h3>;
const ArrowRight = ({ onClick, style }) => <span onClick={onClick} style={{ ...style, cursor: 'pointer' }}>→</span>;
const Answer = ({ children }) => <div style={{ marginLeft: '24px' }}>{children}</div>;

关键说明

  • 用数组存储FAQ数据后,新增/修改问答项只需要修改数组,不用重复写DOM结构,维护更方便
  • expandedId只记录当前展开的项ID,每个项独立判断是否匹配,实现了单独控制
  • 箭头的旋转样式直接通过expandedId === item.id判断,不需要单独的旋转状态,逻辑更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:47:38