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

React类组件访问useRef变量current属性报TypeError问题排查

错误原因
  • 违反React Hook使用规则:所有React Hook(包括useRef、useWebSocket、useMemo、useCallback等)只能在函数组件或自定义Hook的顶层调用,禁止在类组件的内部函数中使用。你代码中定义的Component是类组件Home的实例方法,在这里调用Hook本身就不符合React规则,无法正常执行。
  • 变量访问逻辑完全错误:你在Component方法内部定义的messageHistory是函数内部的局部变量,不会自动挂载到Component类上,你在render中写的Component.messageHistory实际是尝试访问React基类Component的静态属性,这个属性从始至终都不存在,读取其current属性自然会抛出undefined相关报错。
  • 定义的方法从未执行:你只是声明了Component这个实例方法,没有在任何地方调用过,就算没有Hook限制,方法内部的变量也从未完成初始化,根本不可能被外部访问到。
  • 命名冲突:你将类的实例方法命名为Component,和你导入的React基类Component重名,会引发额外的作用域混淆问题。
解决方案

优先推荐方案1,直接将类组件改为函数组件,适配你现有的Hook用法,改造成本极低:

import React, { useCallback, useMemo, useRef  } from "react";
import useWebSocket, { ReadyState } from 'react-use-websocket';
import Select from "react-select"
import "./index.scss";

export default function Home() {
  const socketUrl = process.env.REACT_APP_WEBSOCKET_URL;

  const { sendJsonMessage, lastJsonMessage, readyState } = useWebSocket(
    socketUrl,
  );

  const messageHistory =  useRef([])

  messageHistory.current = useMemo(
    () => messageHistory.current.concat(lastJsonMessage ?? []),
    [lastJsonMessage],
  );

  const handleClickSendMessage = useCallback(() =>
    sendJsonMessage({
      event: 'subscribe',
      subscription: 'test.test',
    }),
    [sendJsonMessage],
  );

  const handleClickUnSendMessage = useCallback(() =>
    sendJsonMessage({
      event: 'unsubscribe',
      subscription: 'test.test',
    }),
    [sendJsonMessage],
  );

  const connectionStatus = {
    [ReadyState.CONNECTING]: 'Connecting',
    [ReadyState.OPEN]: 'Open',
    [ReadyState.CLOSING]: 'Closing',
    [ReadyState.CLOSED]: 'Closed',
    [ReadyState.UNINSTANTIATED]: 'Uninstantiated',
  }[readyState];

  return (
    <React.Fragment>
      <div className="container">
        <div className="signals">
          <button
            onClick={handleClickSendMessage}
            disabled={readyState !== ReadyState.OPEN}
          >
            Subscribe
          </button>
          <button
            onClick={handleClickUnSendMessage}
            disabled={readyState !== ReadyState.OPEN}
          >
            Unsubscribe
          </button>
          <span>The WebSocket is currently {connectionStatus}</span>
          {lastJsonMessage ? (
            <span>
              Last message:{' '}
              {JSON.stringify(lastJsonMessage.data, null, 4)}
            </span>
          ) : null}
          <ul>
            {messageHistory.current.map((message, idx) => (
              <span key={idx}>
                {JSON.stringify(message.data, null, 4)}
              </span>
            ))}
          </ul>
        </div>
      </div>
    </React.Fragment>
  );
}

如果必须保留类组件结构,可以将使用Hook的逻辑抽为独立的子函数组件,在类组件的render方法中渲染该子组件即可:

// 抽离的子函数组件
const WsContent = () => {
  // 把上面所有Hook逻辑、渲染内容都放在这里
}

// 原有类组件
export default class Home extends Component {
  render() {
    return <WsContent />
  }
}

内容的提问来源于stack exchange,提问作者zkbitcoin.com

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 15:15:01