我编写了一个Chrome扩展。在React中,pop .html的实现如下:
const [blogUrls, setblogUrls] = useState<string[]>([]);
useEffect(() => {
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const newBlogUrls = [...blogUrls, ...request.param.blogUrls];
setblogUrls(newBlogUrls);
return true;
});
}, [blogUrls]);
如何避免无限循环?
虽然我写了setblogUrls(newBlogUrls)
,但我知道写[blogUrls]
不好。
但我想写得像[...blogUrls,
。
请告诉我如何解决这个矛盾。
试试这个-
useEffect(() => {
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const newBlogUrls = [...blogUrls, ...request.param.blogUrls];
setblogUrls(newBlogUrls);
return true;
});
return () => chrome.runtime.onMessage.removeEventListener();
}, []);
它将在页面呈现后执行一次。你的依赖项blogUrls在useEffect本身渲染页面后改变。所以useEffect一次又一次地调用自己。这样就形成了无限循环。要渲染一次,只需确保useEffect中的dependency为空。
- 您的代码在每次渲染时添加一个侦听器。
// runs on every render
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
- Remove listener as -
const [blogUrls, setblogUrls] = useState<string[]>([]);
function onBlogUrlsChanged(request) {
const newBlogUrls = [...blogUrls, ...request.param.blogUrls];
setblogUrls(newBlogUrls);
}
useEffect(() => {
chrome.runtime.onConnect.addListener(onBlogUrlsChanged);
return () => {
chrome.runtime.onConnect.removeListener(onBlogUrlsChanged);
}
}, []);
可以通过传递[]
参数只运行一次useEffect
。,我们不会在每次重新渲染组件时都浪费地附加和分离侦听器。
你可以这样做
useEffect(() => {
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
setblogUrls((v) => [...v, ...request.param.blogUrls]);
return true;
});
// Don't forget to clean the listener
return () => chrome.runtime.onMessage.removeEventListener()
}, []);