React Hooks实现点击动态加载元素添加active类的问题求助
修复方案
你的问题核心是违背了React的状态驱动渲染原则:直接尝试修改props或DOM来更新样式,而不是通过状态变化触发组件重渲染。另外全局布尔值active无法区分多个动态生成的Box,需要改为记录当前激活的具体key。
具体修复步骤:
- 重构状态管理:将App中的
active布尔状态改为activeKey,用来存储当前被点击的Box的key值(比如"A"或"B");同时新增displayText状态管理要显示的经文内容,避免直接操作DOM。 - 通过状态控制className:在Box组件中,根据
activeKey是否等于当前Box的key,动态拼接className。 - 移除错误的DOM操作和无效函数:删掉
changeClassName函数和直接调用ReactDOM.render的代码,改用状态更新来控制经文显示。
修复后的完整代码
import React, { useState, useRef } from "https://cdn.skypack.dev/react@17.0.1"; import ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1" const sounds = [ { key: "A", mp3: "https://audiodeploy.netlify.app/8%20El-Mu'minun,%20115-116.mp3", }, { key: "B", mp3: "https://audiodeploy.netlify.app/8%20El-Mu'minun,%20115-116.mp3", } ]; const App = () => { const [keys, setKeys] = useState(["1","2"]); // 记录当前激活的Box的key,初始为null const [activeKey, setActiveKey] = useState(null); // 存储要显示的经文内容 const [displayText, setDisplayText] = useState(null); return ( <> <span id="text"> {displayText && ( <> <p> Then did you think that We created you uselessly and that to Us you would not be returned?"</p> <p>So exalted is Allāh, the Sovereign, the Truth; there is no deity except Him, Lord of the Noble Throne.</p> <p>[Quran, 23:115-116]</p> </> )} </span> <div id="display" className="display"> {sounds.map((sound) => { return ( <Box key={sound.key} text={sound.key} audio={sound.mp3} isActive={activeKey === sound.key} onBoxClick={() => { setActiveKey(sound.key); // 只有点击A/B时显示经文 if (sound.key === 'A' || sound.key === 'B') { setDisplayText(true); } else { setDisplayText(null); } }} /> ); })} </div> </> ); }; const Box = (props) => { const audioRef = useRef(); const handleClick = () => { audioRef.current.play(); props.onBoxClick(); }; return ( <div className={`box ${props.isActive ? 'active' : ''}`} onClick={handleClick} > {props.text} <audio src={props.audio} ref={audioRef} /> </div> ); }; ReactDOM.render(<App />, document.getElementById("root"));
关键说明:
- 动态className:通过
${props.isActive ? 'active' : ''}实现点击时添加active类,状态变化会自动触发组件重渲染更新样式。 - 状态驱动UI:所有UI变化(激活样式、经文显示)都通过状态控制,完全符合React的设计模式,避免了直接操作DOM的风险。
- 组件职责拆分:Box组件只负责自身的渲染和点击事件触发,状态管理交给父组件App,逻辑更清晰。
内容的提问来源于stack exchange,提问作者codproe
相关产品推荐
相关产品推荐

