簡體   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