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?
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 });
}
});
}