Search code examples
reactjsgoogle-chrome-extensionuse-statebrowser-extension

Updating react hook in a chrome extension firing multiple times?


I am using react hooks inside a chrome extension, but when I when updating the state, it is fired multiple times, its not happening when I just console log...

// browser.js
chrome.browserAction.onClicked.addListener(tab => {
    chrome.tabs.sendMessage(tab.id, {
        type: "toggle-popup"
    }, null);
});


// content.js
const [popup, setPopup] = useState(false);
    let number = 1
    const togglePopup = () => setPopup(!popup);
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        if (request.type == "toggle-popup") {
            number++
            togglePopup()
            console.log(number)
            console.log(popup)
        }
})

Its giving me these results...

//1st click on tab icon
2
false

//2nd click on tab icon
3
false
2
true

//3rd click
4
false
3
true
2
true
2
false

I just want it to toggle true / false on click to show / hide a div on the page (I don't want to use popup.js). Any idea what I am doing wrong?


Solution

  • Function component's body is the render function, your code adds a listener on every render

    // Runs on every render
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { setState(...) });
    

    Therefore you need to use React API to handle those cases and removing the closure issues that you having too.

    For this use useEffect and useRef instead of a local variable.

    const Content = () => {
      const [popup, setPopup] = useState(false);
      const numberRef = useRef(0);
    
      useEffect(() => {
        chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
          const togglePopup = () => setPopup((prev) => !prev);
          if (request.type == "toggle-popup") {
            numberRef.current++;
            togglePopup();
          }
        });
      }, []);
    };
    
    ...