React Hooks实现带动画登录注册模态框时useRef与类名操作问题
存在的问题先修正
useRef返回的是包含current属性的对象,你直接操作rightRef.classList会报错,必须通过rightRef.current.classList访问DOM属性- 代码里存在拼写错误:
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
相关产品推荐
相关产品推荐

