javascriptreactjsgoogle-chrome-extension

Object is not being deleted from array after interecting with input checkbox


I am trying to achieve the following:

When input checkbox is true:

When input checkbox is false:

The problem I experience right now is my setSites state updating function is not removing the object from local storage or from sites state

Heres method I use to delete the object and also remove from local storage(suggested via React docs here)

const index = sites.findIndex((site) => site.url.includes(domain));
setSites(sites.filter((site, i) => index !== site[i]));

Heres full app.jsx where I run the above from handleLogs() function

import React, { useState, useEffect } from 'react';
import { createRoot } from 'react-dom/client';

const App = () => {
  const [sites, setSites] = useState([]);

  useEffect(() => {
    chrome.storage.local.get(['sites'], (res) => {
      if (res.sites) {
        setSites(res.sites);
        console.log(`Loaded from storage`, res.sites);
      }
    });
  }, []);

  useEffect(() => {
    chrome.storage.local.set({ sites });
    console.log('Saved to storage:', sites);
  }, [sites]);

  function handleLogs(event) {
    chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
      const domain = tabs[0].url.split('/')[2];
      const fullURL = tabs[0].url;

      if (event.target.checked === false) {
        // remove current site from sites array
        const index = sites.findIndex((site) => site.url.includes(domain));
        setSites(sites.filter((site, i) => index !== site[i]));

        // store new sites in local storage
        chrome.storage.local.set({ sites });

        // remove ?tracking
        const newUrl = fullURL.replace('?tracking', '');
        chrome.tabs.update(tabs[0].id, { url: newUrl });
      } else {
        if (fullURL.includes('?tracking')) {
          console.log('Url already contains tracking');
          return;
        }

        // push new site to array and save to local storage
        setSites((prevSites) => [
          ...prevSites,
          { url: domain }
        ]);
        chrome.storage.local.set({ sites });

        // Decorate URL with parameter
        const params = encodeURI('tracking');
        const url = tabs[0].url;
        const hashStart =
          url.indexOf('#') === -1 ? url.length : url.indexOf('#');
        const querySymbol = url.indexOf('?') === -1 ? '?' : '&';
        var newUrl = `${url.substring(
          0,
          hashStart
        )}${querySymbol}${params}${url.substring(hashStart)}`;

        // Refresh page with new URL
        chrome.tabs.update(tabs[0].id, { url: newUrl });
      }
    });
  }

  return <input type="checkbox" onClick={(event) => handleLogs(event)} />;
};

const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
root.render(<App />);

A bit tricky to debug this in browser as Webpack process is outputting bundled file. Still working on it. But, what am I doing wrong here?


Solution

  • Change setSites(sites.filter((site, i) => index !== site[i])); to:

    setSites((prevSites) => prevSites.filter((site) => !site.url.includes(domain)));

    Then you can probably get rid of the setter for the local storage in your function because you have that being set any time the states changes. So whenever you are updating the states it will update in the local-storage, that is what you want, correct? Calling chrome.storage.local.set({ sites }); in 4 different places gets messy, so it might be in the middle of trying to update one, when it hits another one, causing the confusion in the storage. Having it only in the effect would trigger when the state changes and not anywhere else.

    function handleLogs(event) {
      chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
        const domain = tabs[0].url.split('/')[2];
        const fullURL = tabs[0].url;
    
    if (!event.target.checked) {
      // Remove the site from the state
      setSites((prevSites) =>
        prevSites.filter((site) => !site.url.includes(domain))
      );
    
      // Clean URL
      const newUrl = fullURL.replace('?tracking', '');
      chrome.tabs.update(tabs[0].id, { url: newUrl });
    } else {
      if (fullURL.includes('?tracking')) {
        console.log('URL already contains tracking');
        return;
      }
    
      setSites((prevSites) => [
        ...prevSites,
        { url: domain }
      ]);
    
      const newUrl = `${fullURL}?tracking`; // Example tracking param
      chrome.tabs.update(tabs[0].id, { url: newUrl });
    }
      });
    }