【问题标题】:DOM Element Returning Null on ReactDOM 元素在 React 上返回 Null
【发布时间】:2021-04-09 02:00:31
【问题描述】:

[编辑] 已修复(滚动到底部)

您好,我正在尝试为功能组件选择一个反应元素,当前代码:

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

当我尝试document.getElementById 时,它也会返回 null。

有什么建议吗?谢谢。

已修复

问题是由于该元素是自定义组件而不是默认组件,否则我可以简单地使用copyButton.current

我通过进入组件的 jsx 并将 const Button = (props) =&gt; { etc } 声明更改为 a

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

这篇文章做到了https://reactjs.org/docs/forwarding-refs.html

【问题讨论】:

  • 这看起来像一个函数组件而不是一个类组件,所以你不会使用this 关键字。你试过console.log(copyButton);吗?
  • 这看起来像functional component,所以你不应该做this.copyButton,只是copyButton

标签: javascript reactjs frontend


【解决方案1】:

copyButton 不会在您调用它之前需要测试的第一个渲染周期准备好,您需要使用copyButton.current

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

您不需要测试悬停是否来自您使用ref={copyButton} 的位置,但如果它来自其他地方,则没有任何保证它不会为空(或由于某种原因变为空) ,因此最好始终对其进行测试。

【讨论】:

  • 为什么你认为按钮在初始渲染时还没有准备好?
  • 它是一个函数式组件,“function”会第一次运行来计算它应该显示的内容,代码会在“return”之前运行,它会返回dom,这意味着你可以' t 在第一个循环中使用copyButton,因为它将为空
  • 没有我的朋友。对于功能组件,这是不正确的。我每天都使用 useRef :) 尝试做一个小测试,创建一个功能组件并在声明 useState() 之前在顶部使用 console.log() 并查看它是否被渲染......另外一件事提问者说他​​们想要这个但是:) 希望能消除疑虑:) 最良好的祝愿
  • 它仍然返回 null,我认为问题在于它是自定义组件而不是默认 HTML 元素,有没有办法解决这个问题?
【解决方案2】:

您需要使用copyButton.current 来选择您的ref={copyButton} 按钮。

useRef Hook 是一个函数,它返回一个可变的 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";
  }

【讨论】:

  • 您好,感谢您的回答,它似乎仍然返回 null :/,有什么想法吗?
  • 我认为问题在于它不是默认的 HTML 元素和自定义元素,因为当我将它添加到它上面的 div 时,console.log 似乎可以工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 2017-01-19
  • 2014-07-31
  • 1970-01-01
  • 2017-10-09
  • 1970-01-01
相关资源
最近更新 更多