I have been through many similar QnAs on StackOverflow but I am still confused about why it does not work for me. I understand that state update is not synchronous. Also I am not performing any DOM manipulation.
The full working demo here which demonstrates the issue -
The issue is when you close an open tab the currentTab
state does not update to the (open) tab I am setting to. Because of which the tab's detail area remains blank until I manually click on an open tab's name.
In the above picture I closed the third tab. The expectation was that the tab selection should have auto changed to second tab, but it did not. The code for that same is as below.
function removeTab(id) {
const ntl = tabsList;
const idx = ntl.findIndex((v) => v.id === id);
if (idx !== -1) {
ntl.splice(idx, 1);
if (ntl.length) {
let t = ntl[idx];
console.log("------", t, idx);
if (!t) {
t = ntl[0];
}
console.log(" 1", t, t.id);
setCurrentTab(t.id);
setTabsList([...ntl]);
} else {
const t = newTab();
console.log(" 2", t, t.id);
setCurrentTab(t.id);
setTabsList([t]);
}
}
}
Above the passed id
was that of the third tab. The tabsList
state contains an array with data of each tab. currentTab
contains only the id
of the current tab. As per the console.log
statements above the correct tab's id
is passed, but the currentTab never updates. Even if I put a code like below.
useEffect(() => { console.log('------------>', currentTab) }, [currentTab]);
It never fires in this case.
The removeTab
method is invoked from JSX like below.
{tabsList.map((t) => (
<a
key={t.id ""}
className={
"tab tab-bordered " (currentTab === t.id ? "tab-active" : "")
}
onClick={() => {
setCurrentTab(t.id);
}}
>
{t.name}
<button
onClick={() => {
removeTab(t.id); // On clicking X button we remove tab
}}
>
X
</button>
</a>
))}
CodePudding user response:
There are two problems
- Splice is mutating state directly, to prevent this, you can use spread operator to make a copy of array.
- 2ndly, The Button is inside Anchor Tag and both have onClick, So when the cross button is clicked, Parent anchor onclick is also called, To prevent this, you can do e.stopPropagation().
Here is the edits i made to the codesandbox https://codesandbox.io/s/practical-platform-dvkxrq?file=/src/Tabs.js:3723-3738
CodePudding user response:
The .splice
method is mutating the state directly outside a setState
call, which can lead to unpredictable behaviour. You should either avoid it or create a copy of tabsList
and call splice
on that instead, then update the state with it later.
Try changing the first line in your removeTabs
function to this:
const ntl = tabsList.slice();