React中基于Server-Sent Events实现JSON部分字段更新的问题
问题根源
你的核心问题出在闭包捕获旧值和状态依赖错误:
- useEffect依赖数组为空,导致SSE订阅回调只会捕获组件挂载时的
initialUserData初始值,后续Context更新用户数据后,回调里依然用旧的初始值进行合并,未更新字段无法保留最新状态。 - 代码中的for循环完全多余,对象展开运算符
{...initialUserData, ...receivedData}已经完成了更新字段的合并操作。
修正方案(基于Context API)
假设你通过Context获取当前用户数据和更新方法,直接使用Context中的最新状态进行合并:
// 从Context中获取最新用户数据和更新方法 const { userData, updateUserData } = useContext(UserContext); const [sessionState, setSessionState] = useState(false); useEffect(() => { const unsubscribe = sse.subscribe('playerupdate', (d: any) => { // 基于Context的最新数据合并更新字段,未更新字段自动保留 const updatedUserData = { ...userData, ...d }; updateUserData(updatedUserData); // 注意:字段名需和后端返回一致,初始数据用的是id,这里PlayerId可能是笔误 if (updatedUserData.id > 0) { setSessionState(true); } else if (updatedUserData.id === 0) { setSessionState(false); } }); return unsubscribe; }, [userData, updateUserData]); // 添加依赖,确保回调捕获最新的状态和方法
关键说明
- 移除组件内维护的
initialUserData,直接复用Context提供的userData,彻底避免闭包捕获旧值的问题。 - 将
userData和updateUserData加入useEffect依赖数组,每次Context状态更新时,订阅回调会重新创建,确保拿到最新数据。 - 检查字段名一致性:初始数据里是
id,但原代码判断用的是PlayerId,需和后端返回字段保持一致,否则会导致状态判断逻辑失效。
备选方案(若需保留组件内useState)
如果必须在组件内维护状态,使用函数式更新获取最新状态:
const [userData, setUserData] = useState({ id: 1, name: 'Pol', color: 'black', }); const [sessionState, setSessionState] = useState(false); useEffect(() => { const unsubscribe = sse.subscribe('playerupdate', (d: any) => { // 函数式更新确保拿到最新的state值 setUserData(prevData => { const updated = { ...prevData, ...d }; if (updated.id > 0) { setSessionState(true); } else if (updated.id === 0) { setSessionState(false); } return updated; }); }); return unsubscribe; }, []); // 无需添加依赖,函数式更新不依赖外部state
内容的提问来源于stack exchange,提问作者Thomasino73
相关产品推荐
相关产品推荐

