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
相关产品推荐
相关产品推荐

