You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中获取DOM元素引用以使用rxjs的fromEvent方法订阅事件

问题原因
  • 函数组件误用React.createRef:React.createRef是为类组件设计的API,在函数组件中使用时每次重渲染都会生成全新的ref对象,无法持久化保存DOM引用,因此会出现current: null的问题,函数组件请使用useRef创建ref。
  • 操作ref的时机早于组件挂载:ref的current属性只有在对应DOM元素实际渲染挂载到页面后才会指向该元素,在组件挂载前(比如组件渲染逻辑同步执行时)访问ref,拿到的必然是null。
正确实现方案

函数组件实现(推荐)

使用useRef创建持久化ref,在useEffect回调中执行fromEvent订阅逻辑,useEffect空依赖的回调会在组件挂载完成后执行,此时ref已经绑定到真实DOM,同时要在返回的清理函数中取消订阅避免内存泄漏。

import { useRef, useEffect } from 'react';
import { fromEvent } from 'rxjs';

function App() {
  const buttonWait = useRef(null);

  useEffect(() => {
    // 组件挂载完成后,ref.current已经指向真实DOM元素
    const click$ = fromEvent(buttonWait.current, 'click');
    const subscription = click$.subscribe(() => {
      // 你的事件处理逻辑
      console.log('Wait按钮被点击');
    });

    // 组件卸载时取消订阅,防止内存泄漏
    return () => subscription.unsubscribe();
  }, []);

  return <button ref={buttonWait}>Wait</button>
}

类组件实现

类组件可以正常使用React.createRef,订阅逻辑要放在componentDidMount生命周期中执行,该生命周期触发时DOM已经完成挂载。

import React from 'react';
import { fromEvent } from 'rxjs';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.buttonWait = React.createRef();
    this.subscription = null;
  }

  componentDidMount() {
    const click$ = fromEvent(this.buttonWait.current, 'click');
    this.subscription = click$.subscribe(() => {
      console.log('Wait按钮被点击');
    });
  }

  componentWillUnmount() {
    // 组件卸载时取消订阅
    this.subscription?.unsubscribe();
  }

  render() {
    return <button ref={this.buttonWait}>Wait</button>
  }
}

条件渲染场景的特殊处理

如果按钮是通过状态控制是否渲染的,需要将控制按钮显示的状态变量加入useEffect的依赖数组,确保按钮渲染后再执行订阅逻辑:

import { useState, useRef, useEffect } from 'react';
import { fromEvent } from 'rxjs';

function App() {
  const [showWaitBtn, setShowWaitBtn] = useState(false);
  const buttonWait = useRef(null);

  useEffect(() => {
    // 元素未渲染时直接跳过订阅逻辑
    if (!buttonWait.current) return;

    const click$ = fromEvent(buttonWait.current, 'click');
    const subscription = click$.subscribe(() => {
      console.log('Wait按钮被点击');
    });

    return () => subscription.unsubscribe();
  }, [showWaitBtn]); // 依赖加入控制按钮显示的状态

  return (
    <>
      <button onClick={() => setShowWaitBtn(!showWaitBtn)}>
        切换Wait按钮显示
      </button>
      {showWaitBtn && <button ref={buttonWait}>Wait</button>}
    </>
  )
}

内容的提问来源于stack exchange,提问作者Twilight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 16:27:00