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

React实现点击展开容器时自动关闭其他容器的问题求助

实现折叠面板的互斥展开功能

我有一个接收props的容器组件,点击箭头按钮可以展开/收起内容。现在需要实现:打开某一个内容容器时,其他已打开的容器自动关闭。目前只能通过再次点击对应箭头按钮来关闭容器。

以下是我的子组件代码:

import { useState } from "react";

export default function Question(props) {
    const [clicked, setClicked] = useState(false);
    function clickedElement() {
        return setClicked(!clicked);
    }

    return (
        <div className="question-cont">
            <div className="question-cont-inner">
                <h3>{props.head}</h3>
                <button onClick={() => clickedElement()}>
                    {clicked ? (
                        <img src={props.img2} />
                    ) : (
                        <img src={props.img} />
                    )}{" "}
                </button>
            </div>
            {clicked ? <p>{props.description}</p> : ""}
        </div>
    );
}

父组件代码:

import Question from "../components/Question";
import questions from "../components/Questions";

export default function Sorular() {
    const questionList = questions.map((question) => {
        return (
            <Question
                key={question.id}
                id={question.id}
                head={question.head}
                description={question.description}
                img={question.img}
                img2={question.img2}
            />
        );
    });
    return (
        <div className="sorular-container">
            <div className="sorular-top">
                <div className="sorular-top-back-img">
                    <a href="/">
                        <img
                            src="./images/right-arrow-colorful.png"
                            id="right-arrow-img"
                        />
                    </a>
                </div>
                <div className="sorular-top-head">
                    <img src="./images/conversation.png" />
                    <h4>Sıkça Sorulan Sorular</h4>
                </div>
            </div>
            <div className="sorular-bottom">{questionList}</div>
        </div>
    );
}

解决方案:状态提升到父组件

当前每个Question组件各自维护自己的展开状态,导致组件间无法联动。要实现互斥展开,需要把当前展开的容器ID统一维护在父组件中,子组件根据父组件传递的状态判断是否展开。

修改父组件

在父组件中添加状态管理当前展开的ID,同时给子组件传递点击回调:

import { useState } from "react";
import Question from "../components/Question";
import questions from "../components/Questions";

export default function Sorular() {
    // 存储当前展开的问题ID,初始为null表示全部收起
    const [expandedId, setExpandedId] = useState(null);

    // 处理点击事件:点击当前展开的ID则收起,否则切换到该ID
    const handleQuestionClick = (id) => {
        setExpandedId(expandedId === id ? null : id);
    };

    const questionList = questions.map((question) => {
        return (
            <Question
                key={question.id}
                id={question.id}
                head={question.head}
                description={question.description}
                img={question.img}
                img2={question.img2}
                // 传递是否展开的状态和点击回调
                isExpanded={expandedId === question.id}
                onToggle={() => handleQuestionClick(question.id)}
            />
        );
    });

    return (
        <div className="sorular-container">
            <div className="sorular-top">
                <div className="sorular-top-back-img">
                    <a href="/">
                        <img
                            src="./images/right-arrow-colorful.png"
                            id="right-arrow-img"
                        />
                    </a>
                </div>
                <div className="sorular-top-head">
                    <img src="./images/conversation.png" />
                    <h4>Sıkça Sorulan Sorular</h4>
                </div>
            </div>
            <div className="sorular-bottom">{questionList}</div>
        </div>
    );
}

修改子组件

移除子组件自身的状态,改用父组件传递的属性控制展开/收起:

export default function Question(props) {
    return (
        <div className="question-cont">
            <div className="question-cont-inner">
                <h3>{props.head}</h3>
                <button onClick={props.onToggle}>
                    {props.isExpanded ? (
                        <img src={props.img2} />
                    ) : (
                        <img src={props.img} />
                    )}{" "}
                </button>
            </div>
            {props.isExpanded ? <p>{props.description}</p> : ""}
        </div>
    );
}

原理说明

  • 父组件统一管理所有折叠面板的展开状态,通过expandedId记录当前唯一展开的容器ID;
  • 子组件不再维护自身状态,完全依赖父组件传递的isExpanded判断是否展示内容;
  • 点击按钮时触发父组件的回调函数,更新expandedId,从而实现点击一个面板时自动关闭其他面板的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:15:43