getElementById после динамического добавления в React

Я динамически добавляю карты в свой функциональный компонент React. Карты хранятся в State. Я сопоставляю их и даю каждому из них идентификатор. OnClick на этих картах, я успешно получаю их идентификатор. Теперь я хочу getElementById, чтобы изменить цвет карты:

function Clicked(pressedGifId) {
  if (pressedGifId === 'correctGif') CorrectMatch();
  else WrongMatch();
}

function CorrectMatch(pressedGifId) {
  // / THERE I GET Element: null
  console.log('Element:', document.getElementById(pressedGifId));
}
function WrongMatch() {
  console.log('wrong a match!');
}

export default function GameObject(props) {
  const addedToGameGif = [];
  const [pressedGifId, gifPressed] = useState(null);
  const [photoCards, setPhotoCards] = useState([]);

  useEffect(() => {
    Clicked(pressedGifId);
  }, [pressedGifId]);

  // add randomly picked photos to addedToGameGif array
  // ...

  addedToGameGif.map(gifId =>
    photoCards.push(
      <Card id={gifId} onClick={() => gifPressed(gifId)}>
        text
      </Card>,
    ),
  );

  return <div>{photoCards}</div>;
}

Я пробовал изучать ссылки, но они предназначены только для компонентов класса. Итак, как мне добраться до своего элемента по идентификатору в React?

1 ответ

Решение

Вы можете использовать refв функциональной составляющей. Есть крючок под названиемuseRef.

Примечание. Никогда не взаимодействуйте напрямую с DOM до тех пор, пока не появится доступный api для решения проблемы для этого конкретного варианта использования.

В React не рекомендуется напрямую взаимодействовать с dom. Всегда используйте react apis для взаимодействия с dom. React разработан, чтобы скрыть DOM, потому что они хотят абстрагироваться от DOM. Используя DOM напрямую, вы нарушаете абстракцию и делаете свой код уязвимым для изменений, внесенных в библиотеку.

React поддерживает виртуальную DOM если мы внесем какие-либо изменения в актуальные DOM прямо тогда react не будет знать об этом изменении, и это может привести к неожиданному поведению.

import React, {useState, useRef} from 'react';

export default function GameObject(props) {
  const addedToGameGif = [];
  const [pressedGifId, gifPressed] = useState(null);
  const [photoCards, setPhotoCards] = useState([]);
  const elemRef = useRef(null);

  useEffect(() => {
    Clicked(pressedGifId);
  }, [pressedGifId]);

  // add randomly picked photos to addedToGameGif array
  // ...

  addedToGameGif.map(gifId =>
    photoCards.push(
      <Card ref={elemRef} id={gifId} onClick={() => gifPressed(gifId)}>
        text
      </Card>
    )
  );

  return <div>{photoCards}</div>;
}

Пример из официальных документов.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
Другие вопросы по тегам