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

React中SockJS主题订阅的位置及数据渲染问题

解决SockJS订阅数据渲染及Bootstrap表格更新问题

让我们一步步拆解并解决你的问题:


问题1:订阅逻辑与组件状态管理

你不需要把订阅逻辑移到其他函数,但核心是要把收到的消息存入组件的状态(state)——之前你只把消息打印到控制台,没有触发React的组件更新机制,所以数据无法渲染出来。

实现思路:

React组件只有在state或props变化时才会重新渲染,我们需要在收到SockJS消息时更新组件状态,让表格能实时响应数据变化。SockJsClient本身会在组件挂载时自动建立连接、订阅主题,放在render里完全没问题,不需要手动在其他生命周期函数处理(除非你需要更精细的连接控制)。


问题2:Bootstrap表格动态更新

结合状态管理,我们可以把收到的货币数据以parity为键存储在状态中,渲染表格时直接匹配对应行的数据,再加上开关控制是否接收更新。

完整实现代码(类组件版本):

import React, { Component } from 'react';
import SockJsClient from 'react-stomp';

class CurrencyTracker extends Component {
  constructor(props) {
    super(props);
    // 初始化状态:存储所有货币对数据,开关控制更新
    this.state = {
      currencyData: {
        USDTRY: { buy: '', sell: '' },
        EURTRY: { buy: '', sell: '' },
        GBPTRY: { buy: '', sell: '' },
        EURUSD: { buy: '', sell: '' }
      },
      isTracking: true
    };
  }

  // 处理收到的WebSocket消息
  handleMessage = (msg) => {
    if (!this.state.isTracking) return; // 开关关闭时不更新数据
    
    const { parity, buy, sell } = msg;
    this.setState(prevState => ({
      currencyData: {
        ...prevState.currencyData,
        [parity]: { buy, sell } // 动态更新对应货币对的数据
      }
    }));
  };

  // 切换跟踪状态
  toggleTracking = () => {
    this.setState(prevState => ({
      isTracking: !prevState.isTracking
    }));
  };

  render() {
    const { currencyData, isTracking } = this.state;
    return (
      <div>
        {/* 跟踪开关 */}
        <div className="mb-3">
          <label>
            <input 
              type="checkbox" 
              checked={isTracking} 
              onChange={this.toggleTracking} 
            />
            {isTracking ? '🔄 正在跟踪实时数据' : '⏸️ 已暂停跟踪'}
          </label>
        </div>

        {/* SockJS客户端组件 */}
        <SockJsClient
          url='http://localhost:8080/websocket-example'
          topics={['/topic/currency']}
          onMessage={this.handleMessage}
          ref={(client) => {this.clientRef = client}}
          onDisconnect={() => console.log('WebSocket连接已断开')}
        />

        {/* Bootstrap表格渲染 */}
        <div className="row">
          <div className="col-md-12">
            <table id="currencies" className="table table-hover">
              <thead className="thead-dark">
                <tr>
                  <th>Currency Pair</th>
                  <th>Buy</th>
                  <th>Sell</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>USDTRY</td>
                  <td>{currencyData.USDTRY.buy || '-'}</td>
                  <td>{currencyData.USDTRY.sell || '-'}</td>
                </tr>
                <tr>
                  <td>EURTRY</td>
                  <td>{currencyData.EURTRY.buy || '-'}</td>
                  <td>{currencyData.EURTRY.sell || '-'}</td>
                </tr>
                <tr>
                  <td>GBPTRY</td>
                  <td>{currencyData.GBPTRY.buy || '-'}</td>
                  <td>{currencyData.GBPTRY.sell || '-'}</td>
                </tr>
                <tr>
                  <td>EURUSD</td>
                  <td>{currencyData.EURUSD.buy || '-'}</td>
                  <td>{currencyData.EURUSD.sell || '-'}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default CurrencyTracker;

函数组件(React Hooks)版本:

如果你更习惯用函数组件,逻辑完全一致,只是用useState和useCallback替代类组件的状态和方法:

import React, { useState, useCallback } from 'react';
import SockJsClient from 'react-stomp';

const CurrencyTracker = () => {
  const [currencyData, setCurrencyData] = useState({
    USDTRY: { buy: '', sell: '' },
    EURTRY: { buy: '', sell: '' },
    GBPTRY: { buy: '', sell: '' },
    EURUSD: { buy: '', sell: '' }
  });
  const [isTracking, setIsTracking] = useState(true);

  const handleMessage = useCallback((msg) => {
    if (!isTracking) return;
    const { parity, buy, sell } = msg;
    setCurrencyData(prev => ({
      ...prev,
      [parity]: { buy, sell }
    }));
  }, [isTracking]);

  const toggleTracking = () => {
    setIsTracking(prev => !prev);
  };

  return (
    <div>
      {/* 跟踪开关 */}
      <div className="mb-3">
        <label>
          <input 
            type="checkbox" 
            checked={isTracking} 
            onChange={toggleTracking} 
          />
          {isTracking ? '🔄 正在跟踪实时数据' : '⏸️ 已暂停跟踪'}
        </label>
      </div>

      <SockJsClient
        url='http://localhost:8080/websocket-example'
        topics={['/topic/currency']}
        onMessage={handleMessage}
        ref={(client) => {window.clientRef = client}}
      />

      {/* Bootstrap表格 */}
      <div className="row">
        <div className="col-md-12">
          <table id="currencies" className="table table-hover">
            <thead className="thead-dark">
              <tr>
                <th>Currency Pair</th>
                <th>Buy</th>
                <th>Sell</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>USDTRY</td>
                <td>{currencyData.USDTRY.buy || '-'}</td>
                <td>{currencyData.USDTRY.sell || '-'}</td>
              </tr>
              <tr>
                <td>EURTRY</td>
                <td>{currencyData.EURTRY.buy || '-'}</td>
                <td>{currencyData.EURTRY.sell || '-'}</td>
              </tr>
              <tr>
                <td>GBPTRY</td>
                <td>{currencyData.GBPTRY.buy || '-'}</td>
                <td>{currencyData.GBPTRY.sell || '-'}</td>
              </tr>
              <tr>
                <td>EURUSD</td>
                <td>{currencyData.EURUSD.buy || '-'}</td>
                <td>{currencyData.EURUSD.sell || '-'}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
};

export default CurrencyTracker;

额外优化提示:

  • 数值格式化:可以用toFixed(4)来保留4位小数,比如{currencyData.USDTRY.buy?.toFixed(4) || '-'},让数据更规整。
  • 连接异常处理:利用SockJsClient的onConnectFailure回调处理连接失败的情况,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:17:39