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

如何将基于类的bulma-collapsible React实现改写为Hooks版本

方案1:和原类组件逻辑完全等效的Hooks实现

该方案直接复用bulmaCollapsible.attach原生逻辑,仅用Hooks替代类组件生命周期写法,原有DOM结构无需修改:

import { useRef, useEffect } from 'react';
import bulmaCollapsible from '@creativebulma/bulma-collapsible';

function App() {
  // 用useRef存储容器DOM节点,替代类组件的refs
  const collapsiblesRef = useRef(null);

  useEffect(() => {
    // 组件挂载后执行attach,和原componentDidMount逻辑完全一致
    const collapsibles = bulmaCollapsible.attach(".is-collapsible", {
      container: collapsiblesRef.current
    });
    
    // 组件卸载时销毁实例,避免内存泄漏(原类组件未覆盖的优化点)
    return () => {
      collapsibles.forEach(item => item.destroy());
    };
  }, []);

  return (
    <div className="App">
      <h1 className="title is-1">bulmaCollapsible - ReactJS Integration</h1>
      <div ref={collapsiblesRef} id="accordion_first">
        <article className="message">
          <div className="message-header">
            <p>
              Question 1{" "}
              <a href="#collapsible-message-accordion-1" data-action="collapse">
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-1"
            className="message-body is-collapsible is-active"
            data-parent="accordion_first"
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
        <article className="message">
          <div className="message-header">
            <p>
              Question 2{" "}
              <a href="#collapsible-message-accordion-2" data-action="collapse">
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-2"
            className="message-body is-collapsible"
            data-parent="accordion_first"
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
        <article className="message">
          <div className="message-header">
            <p>
              Question 3{" "}
              <a href="#collapsible-message-accordion-3" data-action="collapse">
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-3"
            className="message-body is-collapsible"
            data-parent="accordion_first"
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
      </div>
    </div>
  );
}

export default App;

方案2:useState状态驱动实现(无需调用attach方法)

该方案完全符合React状态驱动的开发范式,只需要保留bulma-collapsible的CSS样式即可,不用依赖库的JS绑定逻辑,灵活度更高:

import { useState } from 'react';

function App() {
  // 初始化三个折叠项的状态,第一项默认展开
  const [collapseStates, setCollapseStates] = useState({
    'collapsible-message-accordion-1': true,
    'collapsible-message-accordion-2': false,
    'collapsible-message-accordion-3': false,
  });

  // 切换折叠状态,内置手风琴效果:展开当前项时自动关闭其他项
  const toggleCollapse = (id, e) => {
    e.preventDefault();
    const newStates = {};
    Object.keys(collapseStates).forEach(key => {
      newStates[key] = key === id ? !collapseStates[key] : false;
    });
    setCollapseStates(newStates);
  };

  return (
    <div className="App">
      <h1 className="title is-1">bulmaCollapsible - ReactJS Integration</h1>
      <div id="accordion_first">
        <article className="message">
          <div className="message-header">
            <p>
              Question 1{" "}
              <a 
                href="#collapsible-message-accordion-1" 
                onClick={(e) => toggleCollapse('collapsible-message-accordion-1', e)}
              >
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-1"
            className={`message-body is-collapsible ${collapseStates['collapsible-message-accordion-1'] ? 'is-active' : ''}`}
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
        <article className="message">
          <div className="message-header">
            <p>
              Question 2{" "}
              <a 
                href="#collapsible-message-accordion-2" 
                onClick={(e) => toggleCollapse('collapsible-message-accordion-2', e)}
              >
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-2"
            className={`message-body is-collapsible ${collapseStates['collapsible-message-accordion-2'] ? 'is-active' : ''}`}
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
        <article className="message">
          <div className="message-header">
            <p>
              Question 3{" "}
              <a 
                href="#collapsible-message-accordion-3" 
                onClick={(e) => toggleCollapse('collapsible-message-accordion-3', e)}
              >
                Collapse/Expand
              </a>
            </p>
          </div>
          <div
            id="collapsible-message-accordion-3"
            className={`message-body is-collapsible ${collapseStates['collapsible-message-accordion-3'] ? 'is-active' : ''}`}
          >
            <div className="message-body-content">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
              <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
              porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
              Nullam gravida purus diam, et dictum
              <a>felis venenatis</a> efficitur. Aenean ac{" "}
              <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
              sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
              magna a neque. Donec dui urna, vehicula et sem eget, facilisis
              sodales sem.
            </div>
          </div>
        </article>
      </div>
    </div>
  );
}

export default App;

内容的提问来源于stack exchange,提问作者Mr. Hankey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:27:00