WordPress页面间postMessage传递React数据出现旧数据问题求助
核心问题是页面跳转时,postMessage的发送时机与结果页App.js的加载时机不匹配:点击搜索后,FrontPage.js在当前页面发送postMessage,但此时结果页还未初始化,App.js的message事件监听还未注册,因此无法接收到本次的最新消息,反而可能读取到之前会话遗留的旧数据。而你已经确认localStorage中存储的是最新数据,说明存储环节没问题,问题出在消息传递或数据读取的时机上。
方案1:放弃postMessage,结果页主动读取localStorage(最直接)
既然localStorage已经存储了正确的最新数据,完全可以让App.js在初始化时主动读取localStorage,而不是依赖不可靠的postMessage。
修改App.js代码:
import { useEffect } from 'react'; // 在组件初始化时读取localStorage useEffect(() => { const storedData = localStorage.getItem('flightCardsDataArray'); if (storedData) { const latestData = JSON.parse(storedData); console.log('flightCardsDataArray - from localStorage', latestData); // 这里将数据设置到组件状态中,比如 setFlightData(latestData) } // 可选:读取后清空localStorage,避免下次加载时读取到旧数据 localStorage.removeItem('flightCardsDataArray'); }, []); // 保留原有的message监听(可选,兼容其他场景) window.addEventListener('message', (event) => { if (event.data && event.data.type === 'flightCardsDataLoaded') { const data = event.data.data; console.log('flightCardsDataArray - from message', data); // 更新组件状态 } });
同时,FrontPage.js可以保留localStorage的操作,移除不必要的postMessage:
localStorage.clear(); localStorage.setItem('flightCardsDataArray', JSON.stringify(flightCardsDataArray)); isDataLoaded(); // 移除window.postMessage这一行
方案2:调整postMessage发送时机,确保结果页已加载
如果必须使用postMessage,可以通过延迟跳转或让结果页主动请求数据的方式,确保消息能被正确接收。
实现方式:结果页加载后主动请求数据
- FrontPage.js点击搜索时,先存储数据,再打开结果页并监听请求:
localStorage.clear(); localStorage.setItem('flightCardsDataArray', JSON.stringify(flightCardsDataArray)); isDataLoaded(); // 打开结果页窗口 const resultWindow = window.open('/result-page'); // 轮询检查结果页是否加载完成 const checkLoaded = setInterval(() => { if (resultWindow?.readyState === 'complete') { resultWindow.postMessage({ type: 'flightCardsDataLoaded', data: flightCardsDataArray }, '*'); clearInterval(checkLoaded); } }, 100);
- App.js初始化时监听消息:
import { useEffect } from 'react'; useEffect(() => { const handleMessage = (event) => { if (event.data && event.data.type === 'flightCardsDataLoaded') { const latestData = event.data.data; console.log('flightCardsDataArray - from parent', latestData); // 更新组件状态 } }; window.addEventListener('message', handleMessage); // 组件卸载时移除监听 return () => window.removeEventListener('message', handleMessage); }, []);
这种方式需注意窗口引用和同域限制,相对复杂,仅适合必须使用postMessage的场景。
方案3:使用URL传递搜索参数(更符合页面跳转逻辑)
如果flightCardsDataArray是基于搜索参数生成的,可以直接将关键搜索参数通过URL传递到结果页,App.js根据参数重新获取数据,避免前端存储带来的旧数据问题。
实现方式:
- FrontPage.js跳转时携带参数:
// 假设搜索参数为query、date等 const searchParams = new URLSearchParams({ query: '北京到上海', date: '2024-05-20' }); window.location.href = `/result-page?${searchParams.toString()}`;
- App.js读取URL参数并请求数据:
import { useEffect } from 'react'; useEffect(() => { const params = new URLSearchParams(window.location.search); const query = params.get('query'); const date = params.get('date'); // 根据参数调用后端接口获取最新数据 fetch(`/api/flights?query=${query}&date=${date}`) .then(res => res.json()) .then(data => { console.log('flightCardsDataArray - from API', data); // 更新组件状态 }); }, []);
这种方式符合HTTP无状态特性,利于SEO,也避免了前端存储的潜在问题。
优先推荐方案1,代码改动最小且可靠,利用已确认正确的localStorage数据直接读取;如果数据敏感或不适合前端存储,推荐方案3,通过URL参数+后端接口获取数据,更规范。
内容的提问来源于stack exchange,提问作者user1207289

