Элемент DOM, возвращающий нуль при React

[РЕДАКТИРОВАТЬ] БЫЛО ИСПРАВЛЕНО (прокрутите вниз)

Привет, я пытаюсь выбрать элемент реакции для функционального компонента, текущий код:

const Emoji = (props) => {

  const copyButton = useRef(null);

  function handleHover(e) {
    console.log(this.copyButton); //want to select this element
  }

  function handleMouseOut(e) {

  }

  return(
    <div className="wrapper">
      <div id={"emoji-"+props.id} className="emoji" onMouseOver={handleHover} onMouseOut={handleMouseOut}>
        <Button ref={copyButton} className="copyButton" buttonText="Copy" buttonColour="primary" />
        <Button className="button" buttonText="Information" buttonColour=" " />
        <h1>{props.emojiCharacter}</h1>
        <p>{props.emojiName}</p>
      </div>
    </div>
  );
}

export default Emoji;

Я пытаюсь создать приложение, в котором, когда пользователь наводит курсор на этот компонент, появляются кнопки, но когда я пытаюсь их выбрать, я продолжаю получать эту ошибку: TypeError: Cannot read property 'copyButton' of undefined

Он также возвращает null, когда я пытаюсь document.getElementById.

Какие-либо предложения? Спасибо.

ФИКСИРОВАННЫЙ

Проблема заключалась в том, что элемент был настраиваемым компонентом, а не компонентом по умолчанию, иначе я мог бы просто использовать copyButton.current

Я исправил это, перейдя в jsx компонента и изменив объявление const Button = (props) => { etc } на

const Button = React.forwardRef((props, ref) => (
    <div ref={ref} 
    </div>
));

Эта статья сделала это https://reactjs.org/docs/forwarding-refs.html


person KylianMbappe    schedule 02.01.2021    source источник
comment
Это похоже на функциональный компонент, а не на компонент класса, поэтому вы не будете использовать ключевое слово this. вы пробовали только console.log(copyButton);?   -  person Nick    schedule 02.01.2021
comment
Это похоже на functional component, поэтому вам не следует делать this.copyButton, просто copyButton   -  person goto1    schedule 02.01.2021
comment
Пожалуйста, проверьте этот вопрос stackoverflow.com/questions/56541342/   -  person phoenixstudio    schedule 02.01.2021


Ответы (2)


copyButton не будет готов к первому циклу рендеринга, который вам нужно протестировать перед его запуском, и вам нужно будет использовать copyButton.current

const handleMousehover =() =>{
  if(copyButton && copyButton.current){
   // add your code here
  }
}

Вам не нужно будет проверять, поступает ли наведение от того места, где вы использовали ref={copyButton}, но если он поступает откуда-то еще, нет уверенности, что он не будет нулевым (или он стал нулевым по какой-то причине), поэтому это Хорошая практика всегда проверять это.

person phoenixstudio    schedule 02.01.2021
comment
Как вы думаете, почему кнопка не будет готова к первоначальному рендерингу? - person Imran Rafiq Rather; 02.01.2021
comment
это функциональный компонент, и функция будет запускаться в первый раз, чтобы вычислить, что она должна отображать, код будет запускаться перед возвратом, который вернет dom, это означает, что вы не можете использовать copyButton в первом цикле, потому что он будет нулевой - person phoenixstudio; 02.01.2021
comment
Не мой друг. В случае функциональных компонентов это неверно. Я использую useRef каждый день :) Попытайтесь сделать один небольшой тест, создайте функциональный компонент и используйте console.log () вверху непосредственно перед тем, как вы объявите useState (), и посмотрите, будет ли он отображен ... Еще одна вещь, которую спрашивающий говорит, что они хотят этого эффект на Однако :) Надеюсь, что это развеивает сомнения :) С наилучшими пожеланиями - person Imran Rafiq Rather; 02.01.2021
comment
хорошо, я обновлю свой ответ - person phoenixstudio; 02.01.2021
comment
Он по-прежнему возвращает значение null, я думаю, проблема в том, что он является настраиваемым компонентом, а не элементом HTML по умолчанию, есть ли способ исправить это? - person KylianMbappe; 03.01.2021

Для выбора кнопки ref={copyButton} необходимо использовать copyButton.current.

Хук useRef - это функция, которая возвращает изменяемый объект ref, свойство .current которого инициализируется переданным аргументом (initialValue). Возвращаемый объект будет сохраняться в течение всего времени жизни компонента.

const Emoji = (props) => {

  const copyButton = useRef(null);

  function handleHover(e) {
    console.log(copyButton.current); //want to select this element
  }

  function handleMouseOut(e) {

  }

  return(
    <div className="wrapper">
      <div id={"emoji-"+props.id} className="emoji" onMouseOver={handleHover} onMouseOut={handleMouseOut}>
        <Button ref={copyButton} className="copyButton" buttonText="Copy" buttonColour="primary" />
        <Button className="button" buttonText="Information" buttonColour=" " />
        <h1>{props.emojiCharacter}</h1>
        <p>{props.emojiName}</p>
      </div>
    </div>
  );
}

export default Emoji;

ПРИМЕЧАНИЕ. Переходим ко второй части вопроса. Вам нужно будет установить стили в вашей handleHover() функции для отображения и скрытия логики.

Примерно так :) Просто демка. Реализуйте это в соответствии с вашими требованиями

  function handleHover(e) {
    console.log(copyButton.current); 
    copyButton.current.style.display="block";
  }
person Imran Rafiq Rather    schedule 02.01.2021
comment
Привет, спасибо за ответ, похоже, он все еще возвращает null: /, есть идеи? - person KylianMbappe; 03.01.2021
comment
Я думаю, что проблема связана с тем, что он не является элементом HTML по умолчанию, а настраиваемым элементом, потому что, когда я добавляю его в div над ним, console.log, похоже, работает. - person KylianMbappe; 03.01.2021