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

React Hooks实现点击动态加载元素添加active类的问题求助

修复方案

你的问题核心是违背了React的状态驱动渲染原则:直接尝试修改props或DOM来更新样式,而不是通过状态变化触发组件重渲染。另外全局布尔值active无法区分多个动态生成的Box,需要改为记录当前激活的具体key。

具体修复步骤:

  1. 重构状态管理:将App中的active布尔状态改为activeKey,用来存储当前被点击的Box的key值(比如"A"或"B");同时新增displayText状态管理要显示的经文内容,避免直接操作DOM。
  2. 通过状态控制className:在Box组件中,根据activeKey是否等于当前Box的key,动态拼接className。
  3. 移除错误的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:03:01