组件未将元素存储到变量中(也许它还没有渲染?



我正在尝试将DOM元素存储在React组件内的变量中。

我在组件的 render() 函数中声明此变量,如下所示:

render() {
  const aside = document.querySelector('aside');
    ...
    ...
}

鉴于这是在return之前声明的,我猜,在此声明时,const asidenull,也许这就是它不起作用的原因。

我应该在哪里声明这个变量?或者有没有更好的方法来在 React 中存储这样的 DOM 元素变量?

附带问题:这个变量是引用浏览器 DOM 元素还是 React 的虚拟 DOM 元素?

这是完整的组件:

import React, { Component } from 'react';
class Sidebar extends Component {
  render() {
    const aside = document.querySelector('aside');
    function hideSidebar() {
      aside.classList.remove('show');
    }
    function openSidebar() {
      aside.classList.add('show');
      aside.addEventListener('mouseleave', 'hideSidebar');
    }
    return (
        <aside>
          <svg onClick={openSidebar}
            ...
          </svg>
          <ul>
            <li onClick={chooseSvg}>Dreamcast</li>
            <li onClick={chooseSvg}>Jetson</li>
          </ul>
        </aside>
    );
  }
}
export default Sidebar;

当我单击<svg>元素并触发onClick={openSidebar}时,我收到错误:

TypeError: Cannot read property 'classList' of null

您的假设是正确的,即您正在获得null的结果,因为在调用render时 DOM 尚未更新。当你需要引用原始 DOM 元素时,React 提供了一个 Ref 的概念来安全地做到这一点。你可以在 Refs 和 DOM 下的官方 React 文档中阅读有关 Refs 以及如何使用它们的信息。

在大多数情况下,React 为我们提供了比像这样手动操作 DOM 更好的选择。对于上述情况,我强烈建议使用组件状态来保存值(例如。 isSidebarOpen ),并根据此状态属性切换className。类似于以下示例的内容:

import React, { Component } from 'react';
class Sidebar extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isSidebarOpen: false,
    };
    this.openSidebar = this.openSidebar.bind(this);
    this.hideSidebar = this.hideSidebar.bind(this);
  }
  openSidebar() {
    this.setState({
      isSidebarOpen: true,
    });
  }
  hideSidebar() {
    this.setState({
      isSidebarOpen: false,
    });
  }
  render() {
    let asideClassName = this.state.isSidebarOpen
      ? 'show'
      : 'hide';
    return (
        <aside className={asideClassName} onMouseLeave={this.hideSidebar}>
          <svg onClick={this.openSidebar}
            ...
          </svg>
          <ul>
            <li onClick={chooseSvg}>Dreamcast</li>
            <li onClick={chooseSvg}>Jetson</li>
          </ul>
        </aside>
    );
  }
}
export default Sidebar;

首先,直接在 React 组件中操作 dom 不是一个好主意。除了原始答案之外,您还可以使用 react 钩子 - https://reactjs.org/docs/hooks-intro.html

import React, { useState } from "react";
function Sidebar() {
  const [sideBarOpen, setSideBarOpen] = useState(false);
  const hideSideBar = () => {
    setSideBarOpen(false);
  };
  const showSideBar = () => {
    setSideBarOpen(true);
  };
  const chooseSvg = () => {
    //
  };
  return (
    <aside className={sideBarOpen ? "show" : "hide"} onMouseLeave={hideSideBar}>
      <svg onClick={showSideBar}>
        //...
      </svg>
      <ul>
        <li onClick={chooseSvg}>Dreamcast</li>
        <li onClick={chooseSvg}>Jetson</li>
      </ul>
    </aside>
  );
}
export default Sidebar;

相关内容

最新更新