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

React Hooks实现带动画登录注册模态框时useRef与类名操作问题

存在的问题先修正

  1. useRef 返回的是包含 current 属性的对象,你直接操作 rightRef.classList 会报错,必须通过 rightRef.current.classList 访问DOM属性
  2. 代码里存在拼写错误:rignt 应为 right

优化方案

你用到了 styled-components,完全不需要手动操作DOM的classList,React最佳实践是状态驱动视图,直接用你已经定义的 isActive 状态控制样式即可,彻底不需要用ref改类名。

方案1:用styled-components传参控制(最推荐)

直接把状态通过props传给styled组件,在样式定义里直接判断,不需要额外定义CSS类:

// 组件调用处传参
<RightSide
  isRight={isActive}
  switchLogin={switchToSignin}
  switchReg={switchToSignup}
  onClick={changeAuth}
/>

对应styled组件定义:

const RightSide = styled.div`
  /* 原有基础样式 */
  transition: all 0.5s ease;
  /* 直接用props控制原来.right/.left对应的样式 */
  transform: ${props => props.isRight ? 'translateX(0)' : 'translateX(-100%)'};
  background: ${props => props.isRight ? '#2196f3' : '#f44336'};
`

方案2:动态拼接className(如果要保留原有CSS类)

如果你的样式是写在独立CSS文件里的,直接在className属性里拼接类名即可:

<RightSide
  className={`right-side ${isActive ? 'right' : 'left'}`}
  switchLogin={switchToSignin}
  switchReg={switchToSignup}
  onClick={changeAuth}
/>

原来组件挂载时手动加right类的useEffect可以直接删掉,因为isActive默认值是true,第一次渲染就会自动带上right类。

修正后完整参考代码

import { useDispatch, useSelector } from 'react-redux';
import { useState, useRef } from 'react';
import styled from 'styled-components';
import { hideModal } from './modalSlice';
import Login from './Login';
import Register from './Register';

export default function Modal() {
  const dispatch = useDispatch();
  const { isModal } = useSelector((state) => state.modal_Reducer);
  // 没有其他DOM操作需求的话mainRef也可以删掉
  const mainRef = useRef();
  const [isActive, setIsActive] = useState(true);

  const changeAuth = () => {
    setIsActive(prevState => !prevState);
  };

  const onHideModal = (e) => {
    if (e.target === e.currentTarget) {
      dispatch(hideModal());
    }
  };

  if (!isModal) return null;

  const switchToSignup = isActive ? "Register" : "Login";
  const switchToSignin = isActive ? "Login" : "Register";

  return (
    <ModalBackground onClick={onHideModal}>
      <Main_Container>
        <Auth_box ref={mainRef}>
          {isActive && <Login />}
          {!isActive && <Register />}
        </Auth_box>
        <RightSide
          isRight={isActive}
          switchLogin={switchToSignin}
          switchReg={switchToSignup}
          onClick={changeAuth}
        />
      </Main_Container>
    </ModalBackground>
  );
}

const ModalBackground = styled.div`
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
`;

const Main_Container = styled.div`
  width: min(90%, 800px);
  height: 500px;
  position: relative;
  overflow: hidden;
  border-radius: 10px;
`;

const Auth_box = styled.div`
  width: 50%;
  height: 100%;
  padding: 2rem;
`;

const RightSide = styled.div`
  position: absolute;
  top: 0;
  right: 0;
  width: 50%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 1.5rem;
  cursor: pointer;
  transition: transform 0.5s ease;
  transform: ${props => props.isRight ? 'translateX(0)' : 'translateX(-100%)'};
  background: linear-gradient(45deg, #2196f3, #21cbf3);
`;

内容的提问来源于stack exchange,提问作者spec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 14:54:02