繁体   English   中英

React TypeScript document.getElementById总是选择第一个实例

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM