[英]React TypeScript document.getElementById always selects the first instance
我已经渲染了两个相同的组件
<div><Modal title='Join'/></div>
<div><Modal title='Login'/></div>
模态分量是这样的
import React, {useState} from 'react';
import {Join} from './join';
import {Login} from './login';
interface propsInterface {
title: string;
}
const Modal: React.FC<propsInterface> = (props) => {
const [state, setState] = useState({showLogin: props.title === "login" ? false : true});
let modalState = false;
function toggleLogin(event: any) {
setState({...state, showLogin: !state.showLogin});
}
function toggleModal(event: any) {
if (event.target.id !== 'modal') return;
modalState = !modalState;
const modal = document.getElementById('modal'); <<==this always selects the first one
const card = document.getElementById('card'); <<==this always selects the first one
if (modal && card && modalState === true) {
modal.style.display = "flex";
modal.animate([{backgroundColor: 'rgba(0, 0, 0, 0)'}, {backgroundColor: 'rgba(0, 0, 0, 0.6)'}], {duration: 200, easing: 'ease-in-out', fill: 'forwards'});
card.animate([{opacity: 0}, {opacity: 1}], {duration: 200, easing: 'ease-in-out', fill: 'forwards'});
card.animate([{transform: 'translateY(-200px)'}, {transform: 'translateY(0)'}], {duration: 200, easing: 'ease-in-out', fill: 'forwards'});
}
if (modal && card && modalState === false) {
modal.animate([{backgroundColor: 'rgba(0, 0, 0, 0.6)'}, {backgroundColor: 'rgba(0, 0, 0, 0)'}], {duration: 200, easing: 'ease-in-out', fill: 'forwards'});
card.animate([{opacity: 1}, {opacity: 0}],{duration: 200, easing: 'ease-in-out', fill: 'forwards'});
card.animate([{transform: 'translateY(0)'}, {transform: 'translateY(-200px)'}], {duration: 200, easing: 'ease-in-out', fill: 'forwards'});
setTimeout(() => modal.style.display = "none", 200);
}
}
return (
<div>
<div className='modal' id='modal' onClick={toggleModal}>
<div className='card' id='card'>
{props.title}
{state.showLogin
? <Login toggleLogin={toggleLogin} toggleModal={toggleModal}/>
: <Join toggleLogin={toggleLogin} toggleModal={toggleModal}/>}
</div>
</div>
<div onClick={toggleModal} className='modal-title' id='modal'> {props.title}</div>
</div>
);
}
export {Modal};
因为当我使用时,dom中现在有2个组件
const modal = document.getElementById('modal');
组件的第一个实例按预期工作,但是第二个实例选择第一个实例,而不选择第二个实例。
有一种方法只能在此组件中获取getElementById吗?
同一页上只能有一个具有给定id的元素,在这种情况下,您可能要使用类并使用document.getElementsByClassName("classname")
,这将返回具有给定类名的元素数组。
希望这可以帮助
可以将字段的ID作为props传递,然后设置其id属性,而不是将ID设置为``模态'',然后对它们使用getElementById。
您可以这样做:
<Modal title='Join' UniqId="modal1"/>
<Modal title='Login' UniqId="modal2"/>
然后,在组件中,您可以执行以下操作:
<div className='modal' id={props.UniqId} onClick={toggleModal}>
之后,在您的JS文件中,您可以使用以下ID:
const modal1 = document.getElementById('modal1');
const modal2 = document.getElementById('modal2');
这样做的方式似乎仍然是在使用事件发生后使用原始JavaScript来操纵DOM元素的心态。
通常,在React世界中,您应该将所有内容都链接到render()
方法中,该方法在每当react组件中的状态或属性发生更改时都会引发。
因此,在您遇到的情况下,我将删除所有获取DOM元素的代码(例如您的document.getElementById
代码),然后纯粹从状态更改中进行工作。 很抱歉,这不是完整的代码,因为我不确定您的UI应该是什么样。
const Modal: React.FC<propsInterface> = (props) => {
const [state, setState] = useState({ showLogin: props.title === "login" ? false : true, showModal: false, showCard: false });
function toggleLogin() {
setState({ showLogin: !state.showLogin });
}
function toggleModal() {
setState({ showModal: !state.showModal, showCard: !state.showCard });
}
const modalClassName = state.showModal ? 'modal show' : 'modal';
const cardClassName = state.showLogin ? 'card show' : 'card';
return (
<div>
<div className={modalClassName} onClick={toggleModal}>
<div className={cardClassName}>
{props.title}
{state.showLogin
? <Login toggleLogin={toggleLogin} toggleModal={toggleModal}/>
: <Join toggleLogin={toggleLogin} toggleModal={toggleModal}/>}
</div>
</div>
<div onClick={toggleModal} className='modal-title' id='modal'> {props.title}</div>
</div>
);
}
实际上发生的是,当调用toggleModal
方法时,它仅在true / false之间切换两个状态属性。 这将导致组件重新呈现,并且类名称在div
元素上更改。
由此,您将需要将所有动画移到CSS文件中,并可能在其中使用动画(css动画不是我的最大技能)。 这不是对您拥有的东西的简单更改,但是我将始终将样式和动画保留在组件外部和css文件中,并且始终从渲染工作,而不是尝试在渲染后操作React节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.