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

React外汇交易应用中useRef存前值渲染显示更新后值问题求解

核心问题

你的代码主要存在3个错误导致表现异常:

  • 违反React reducer纯函数规范:在reducer中直接修改原状态对象、操作useRef产生副作用,会导致状态更新时序和ref赋值时序不匹配
  • 前值存储结构不合理:单个ref只能存储最后一次更新的标的前值,多标的场景下其余标的渲染时无法拿到自身对应的前值
  • 状态更新不符合不可变原则:你对state.setData做了浅拷贝,但内部每个标的对象仍使用原引用,直接修改原对象属性会导致不可预期的渲染问题

修复方案

步骤1:调整前值存储结构

将存储前值的ref改为对象结构,以标的代码为key存储每个标的的历史值:

// 替换原来的temp、refer ref
const prevDataRef = useRef({});

步骤2:移除reducer中的副作用逻辑

把存储前值的逻辑从reducer移到WebSocket的onmessage回调中,reducer仅负责返回新状态,同时修改reducer为不可变更新:

// ws onmessage回调修改
ws.current.onmessage = (evt) => {
  const data = JSON.parse(evt.data);
  const evtData = data.data;
  // 先存旧值到ref
  const targetSymbol = evtData.s;
  if (state.setData?.[targetSymbol]) {
    prevDataRef.current[targetSymbol] = {...state.setData[targetSymbol]};
  }
  dispatch({ type: Actions.UpdateData, payload: evtData });
};

// reducer 修改
case Actions.UpdateData:
  const incomingData = action.payload;
  if (!state.setData) return state;
  const targetSymbol = incomingData.s;
  if (!state.setData[targetSymbol]) return state;
  // 不可变更新:创建新的标的对象,不修改原对象
  const newSetData = {
    ...state.setData,
    [targetSymbol]: {
      ...state.setData[targetSymbol],
      stock_change_p: incomingData.pch?.toFixed(2),
      ask_price: incomingData.ap,
      ask_volume: incomingData.av,
      bid_price: incomingData.bp,
      bid_volume: incomingData.bv,
      stock_change: incomingData.ch,
      stock_current_price: incomingData.c,
      stock_high: incomingData.h,
      stock_low: incomingData.l,
      stock_open: incomingData.o,
      stock_volume: incomingData.v,
    }
  };
  return { ...state, setData: newSetData };

步骤3:修改渲染时前值取值逻辑

渲染时从preDataRef中取当前标的对应的前值做对比:

const onValueChange = (el, field) => {
  const prevVal = prevDataRef.current[el.stock_symbol]?.[field];
  if (prevVal === undefined) return 'white';
  if (el[field] === prevVal) return 'blue';
  return el[field] > prevVal ? 'green' : 'red';
};

// 调用示例
<td
  style={{ backgroundColor: onValueChange(el, "stock_current_price") }}
>
  {el.stock_current_price}
</td>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:54:05