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

React中如何更新对象数组 实现交易对数据无重复展示

问题根源

当前代码出现重复Pair条目的核心原因有三个:

  • 组件内部游离定义的DATA数组在每次组件重渲染时都会被重置为空数组,回调逻辑未做存在性判断,收到推送就全量push新条目
  • WebSocket订阅逻辑未做生命周期管控,组件每次重渲染都会重复创建订阅,多份回调同时触发会重复写入数据
  • 回调更新状态时直接操作临时数组,没有基于已有的行情状态做匹配更新,旧条目不会被替换只会追加新条目
实现方案

废弃独立的DATA临时数组,所有行情数据统一存在TickerFeed状态中;收到WebSocket推送时,以Pair字段为唯一标识做增量更新:已存在的Pair直接替换价格、成交量等字段,不存在的Pair新增到列表中;同时将订阅逻辑放到useEffect中,组件挂载时仅订阅一次,卸载时取消订阅避免内存泄漏。
为了提升匹配效率,更新时先将已有状态转为Pair为键的Map结构,避免每次遍历数组查找,更新完成后再转回数组存入状态。

修复后完整代码
import { useState, useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
// 按项目实际路径导入DataTable相关组件
// import { DataTable } from 'xxx';

function App() {
  const [TickerFeed, SetTickerFeed] = useState([]);

  useEffect(() => {
    // 组件挂载时初始化一次订阅
    const subscription = orionUnit.priceFeed.ws.subscribe("allTickers", {
      callback: (tickers) => {
        let keys = zodUtil.util.objectKeys(tickers);
        let values = zodUtil.util.objectValues(tickers);

        SetTickerFeed(prevFeed => {
          // 把已有数据转成以Pair为键的Map,查找复杂度O(1)
          const tickerMap = new Map(prevFeed.map(item => [item.Pair, item]));

          for (let i = 0; i < keys.length; i++) {
            const currentPair = keys[i];
            // 已存在的Pair覆盖最新数据,不存在的自动新增
            tickerMap.set(currentPair, {
              Pair: currentPair,
              LastPrice: values[i].lastPrice, 
              Volume: values[i].volume, 
              OpenPrice: values[i].openPrice, 
              LowPrice: values[i].lowPrice, 
              HighPrice: values[i].highPrice
            })
          }

          // 转回数组更新状态
          return Array.from(tickerMap.values());
        })
      }
    });

    // 组件卸载时取消订阅,避免内存泄漏和重复回调
    return () => {
      // 若SDK取消订阅方法名不是unsubscribe,替换成对应方法即可
      subscription.unsubscribe?.();
    }
  }, []); // 空依赖数组,保证仅在组件挂载时执行一次订阅逻辑

  return (
    <View style={styles.container}>
      <DataTable>
        <DataTable.Header>
          <DataTable.Title>Pair</DataTable.Title>
          <DataTable.Title>LastPrice</DataTable.Title>
          <DataTable.Title>Volume</DataTable.Title>
          <DataTable.Title>OpenPrice</DataTable.Title>
          <DataTable.Title>LowPrice</DataTable.Title>
          <DataTable.Title>HighPrice</DataTable.Title>
        </DataTable.Header>

        {TickerFeed.map((item) => (
          <DataTable.Row key={item.Pair}>
            <DataTable.Cell>{item.Pair}</DataTable.Cell>
            <DataTable.Cell numeric>{item.LastPrice}</DataTable.Cell>
            <DataTable.Cell numeric>{item.Volume}</DataTable.Cell>
            <DataTable.Cell numeric>{item.OpenPrice}</DataTable.Cell>
            <DataTable.Cell numeric>{item.LowPrice}</DataTable.Cell>
            <DataTable.Cell numeric>{item.HighPrice}</DataTable.Cell>
          </DataTable.Row>
        ))}
      </DataTable>
    </View>
  );
}

export default App;
逻辑说明
  • 首次收到全量tickers推送时,Map为空,所有Pair会作为新条目写入,完成初始化加载
  • 后续收到WebSocket推送时,已存在的Pair会直接覆盖最新的行情字段,不会新增重复条目
  • 若推送中出现之前不存在的新Pair,会自动追加到列表中,不需要额外处理
  • 使用函数式状态更新SetTickerFeed(prevFeed => {})可以保证每次更新拿到的都是最新的行情列表,避免闭包导致的旧状态问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 20:36:32