React 组件渲染问题

38 天前
 izzy27

我在写一个 chrome 插件

content script 会给页面增加一个按钮,点击这个按钮后

  1. content script会发消息,service workersidePanel都会监听这个消息
  2. service worker收到消息后,会打开侧边栏
  3. sidePanel监听消息,然后会把页面信息渲染出来

service worker的代码

chrome.runtime.onMessage.addListener((req, sender) => {
  if (req.type === 'openSidePanel') {
    chrome.sidePanel.open({ tabId: sender.tab.id });
  }
});

侧边栏的伪代码:

const SidePanel = () =>{
	const [info, setInfo] = useState('');
    
    useEffect(()=>{
    	chrome.runtime.onMessage.addListener((req)=> setInfo(req.info))
    })

	return ({info===''?'loading...':info})
}

但是有个非常奇怪的现象,就是我第一次点击,侧边栏能正常打开,但是会显示 loading

只有第二次点击之后,才会把 info 信息渲染出来

我的猜测是,第一次点击的时候,组件刚渲染出来,useEffect 里面监听消息没有生效,第二次点击后,组件已经渲染完毕了,useEffect 里面可以监听到消息了,如果是这样的话,应该怎么解决?

不是很熟悉前端,请教一下大家怎么解决

1029 次点击
所在节点    React
5 条回复
wdking
38 天前
使用 uselayouteffect
realJamespond
38 天前
useEffect(()=>{
chrome.runtime.onMessage.addListener((req)=> setInfo(req.info))
},[])
要加 deps 啊,不然每次 render 都执行
zkkz
38 天前
在 service worker 暂存信息,等 SidePanel 渲染完成后,再与 service worker 通信获取信息。
Albertcord
38 天前
怀疑是没有同步更新导致的,可以尝试在侧边栏实现里这么写:
```JavaScript
import {flushSync} from 'react-dom';
// ...
useEffect(()=>{
chrome.runtime.onMessage.addListener((req)=> {
flushSync(() => {
setInfo(req.info);
});
})
return () => {
// unsubscribe addListener
}
}, [])
```
izzy27
38 天前
@zkkz 这个方法可以的,感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1039830

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX