我有一个Popup.jsx
和一个Background.js
。这个弹出窗口创建了一个与后台service worker的长期连接。
我在我的Popup.jsx
中保持一个状态,它看起来像这样
const [projectDetail, setProjectDetail] = useState({ projectCode: null })
我的Popup.jsx
的useEffect
是这样的,
useEffect(() => {
port = chrome.runtime.connect({ name: 'Background Connection' })
port.onMessage.addListener(({ action, payload }) => {
switch (action) {
case ACTION.SET_PROJECT_DETAIL:
setProjectDetail(payload);
break;
case ACTION.CHECK_STATE:
console.log(projectDetail)
break;
default:
break;
}
})
port.postMessage({ action: ACTION.GET_PROJECT_DETAIL })
return () => {
port.disconnect()
}
}, [])
正如您所看到的,在port
变量(在组件作用域之外定义)上附加onMessage
的侦听器后,我正在向Background.js
发送消息以获取项目详细信息。Background.js
按照以下代码响应:
chrome.runtime.onConnect.addListener(function (port) {
// console.log("🚀 ~ file: index.js ~ line 182 ~ chrome.runtime.onConnect.addListener ~ port", port)
port.onMessage.addListener(function ({ action, payload }) {
if (action === ACTION.GET_PROJECT_DETAIL) {
port.postMessage({ action: ACTION.SET_PROJECT_DETAIL, payload: { projectCode: "Some value"} })
}
// ...Removed more code for brevity
});
});
假设我有一个用户交互按钮,它告诉Background.js
向Popup.jsx
发送一条与case ACTION.CHECK_STATE:
匹配的消息,所以很明显,我希望Popup.jsx
能够控制台记录{projectCode: "Some value"}
的值,因为组件中的状态已经更新(我已经通过使用ReactDevTools
验证了它)。
但是,它打印的{ projectCode: null }
是初始状态值。
注意:用户交互不会在组件挂载后立即发生,所以我不是想在设置后立即获得状态值。
我无法在addListener
的回调函数中获得更新的状态值。我不知道我哪里做错了。
不能工作的原因是port
变量是在功能组件本身之外声明的。
最初,Popup.jsx
是这样定义的,
//...import statements
let port = null;
const Popup = () => {
port = chrome.runtime.connect({ name: 'Background Connection' });
//...more code
}
之后,我把它改成,
//...import statements
const Popup = () => {
let port = chrome.runtime.connect({ name: 'Background Connection' });
//...more code
}
我不能确切地说到底是什么原因。然而,在我看来,这似乎是范围问题。