如何将基于类的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
相关产品推荐
相关产品推荐

