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

React中动态修改classList后样式未生效问题求助

React Hover样式不生效问题解决

问题概述

使用React构建Web应用,Slice组件包含两个Project组件,期望通过hover事件修改它们的宽度。已确认minimized和maximized类已添加到元素的classList中,但对应的样式未生效,修改其他样式验证也无效。

相关代码

slice.js

import { useState, useEffect } from "react";
import Project from "./Project";
import "./Slice.css";
import { v4 as uuidv4 } from "uuid";

export default function Slice(props) {
    const data = props.sliceData.projects;
    const [projectElements, setProjectElements] = useState([]);
    const projectUIDs = [uuidv4(), uuidv4()];

    useEffect(() => {
        const elements = [
            document.getElementById(projectUIDs[0]),
            document.getElementById(projectUIDs[1]),
        ];
        setProjectElements(elements);

        return () => {
            elements.forEach((element, index) => {
                if (element) {
                    element.removeEventListener("mouseover", () =>
                        handleMouseOver(index)
                    );
                    element.removeEventListener("mouseout", () =>
                        handleMouseOut(index)
                    );
                }
            });
        };
    }, []);

    const handleMouseOver = (index) => {
        projectElements[index].classList.add("maximized");
        projectElements[index ^ 1].classList.add("minimized");
    };

    const handleMouseOut = (index) => {
        projectElements[index].classList.remove("maximized");
        projectElements[index ^ 1].classList.remove("minimized");
    };

    const generateProjects = () => {
        return data.map((project, index) => (
            <Project
                key={uuidv4()}
                uid={projectUIDs[index]}
                projectData={project}
                onMouseEnter={() => handleMouseOver(index)}
                onMouseLeave={() => handleMouseOut(index)}
            />
        ));
    };

    return <div className="slice">{generateProjects()}</div>;
}

Slice.css

.slice {
    height: 50vh;
    width: 100%;
    display: flex;
}

.projectWrapper {
    display: flex;
    justify-content: space-around;
    align-items: center;
    color: black;
    padding: 2rem;
    overflow: hidden;
    transition: flex-grow 0.5s ease-in-out;
    width: 100%; /* Ensure each projectWrapper occupies the full width */
}

.projectWrapper img {
    flex: 1; /* Use flex shorthand to distribute space equally */
    max-width: 50%; /* Set maximum width for the image */
}

.projectWrapper h1 {
    flex: 1; /* Use flex shorthand to distribute space equally */
    font-size: 2rem;
    font-weight: 700;
    max-width: 40%; /* Set maximum width for the h1 element */
}
.minimized{
    flex-grow: 0;
}
.maximized{
    flex-grow: 1;
}

@media (max-aspect-ratio: 155/100) {
    .slice{
        flex-direction: column;
        height: fit-content;
    }
    .projectWrapper{
        height: 50vh;
    }
}

@media (max-width: 450px) {
    .projectWrapper{
        flex-direction: column;
        align-items: center;
    }
    .projectWrapper h1{
        text-align: center;
        width: 80%;
        max-width: none;
    }
    .projectWrapper img{
        width: 80%;
        max-width: none;
    }
}

问题原因

  1. 样式优先级与flex布局冲突:.minimized和.maximized是单独的类选择器,优先级不足以正确作用于带有.projectWrapper类的元素;同时.projectWrapper设置的width:100%干扰了flex布局中flex-grow的效果。
  2. 直接操作DOM不符合React范式:通过document.getElementById操作元素classList,容易出现渲染时机问题,且不利于React状态管理。
  3. 组件key设置不当:使用uuidv4()作为key会导致组件频繁重渲染,引发不必要的DOM操作。

解决方案

1. 修复样式规则

修改CSS中的类选择器,提升优先级并调整flex属性:

/* 替换原有的.minimized和.maximized规则 */
.projectWrapper.minimized {
    flex-grow: 0;
    flex-basis: 20%; /* 可根据需求调整最小宽度 */
    transition: all 0.5s ease-in-out;
}

.projectWrapper.maximized {
    flex-grow: 1;
    flex-basis: 80%; /* 对应最大化后的宽度占比 */
    transition: all 0.5s ease-in-out;
}

/* 移除.projectWrapper中的width:100% */
.projectWrapper {
    display: flex;
    justify-content: space-around;
    align-items: center;
    color: black;
    padding: 2rem;
    overflow: hidden;
    transition: all 0.5s ease-in-out;
}

2. 改用React状态管理类名

重写Slice组件,通过状态控制类名,避免直接操作DOM:

import { useState } from "react";
import Project from "./Project";
import "./Slice.css";
import { v4 as uuidv4 } from "uuid";

export default function Slice(props) {
    const data = props.sliceData.projects;
    const projectUIDs = [uuidv4(), uuidv4()];
    const [projectClasses, setProjectClasses] = useState(["", ""]);

    const handleMouseOver = (index) => {
        setProjectClasses(prev => {
            const newClasses = [...prev];
            newClasses[index] = "maximized";
            newClasses[index ^ 1] = "minimized";
            return newClasses;
        });
    };

    const handleMouseOut = (index) => {
        setProjectClasses(prev => {
            const newClasses = [...prev];
            newClasses[index] = "";
            newClasses[index ^ 1] = "";
            return newClasses;
        });
    };

    const generateProjects = () => {
        return data.map((project, index) => (
            <Project
                key={projectUIDs[index]}
                uid={projectUIDs[index]}
                projectData={project}
                className={projectClasses[index]}
                onMouseEnter={() => handleMouseOver(index)}
                onMouseLeave={() => handleMouseOut(index)}
            />
        ));
    };

    return <div className="slice">{generateProjects()}</div>;
}

3. 调整Project组件接收className属性

确保Project组件将传入的className应用到根元素:

// Project.js
export default function Project({ uid, projectData, className, onMouseEnter, onMouseLeave }) {
    return (
        <div
            id={uid}
            className={`projectWrapper ${className}`}
            onMouseEnter={onMouseEnter}
            onMouseLeave={onMouseLeave}
        >
            <img src={projectData.image} alt={projectData.title} />
            <h1>{projectData.title}</h1>
        </div>
    );
}

额外注意事项

  • 避免使用动态生成的uuidv4()作为组件key,改用固定的唯一标识(如示例中的projectUIDs),防止组件频繁重渲染。
  • 移除原代码中useEffect操作DOM的逻辑,通过React状态管理实现样式控制,符合React的数据流理念。

内容的提问来源于stack exchange,提问作者gray hat failure

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:02:04