我在StackOverflow上经历过许多类似的QnAs,但我仍然不明白为什么它对我不起作用。我知道状态更新是不同步的。而且,我不会执行任何DOM操作。
这里的完整演示演示了这个问题-- https://codesandbox.io/s/falling-pine-kljujf?file=/src/Tabs.js
在本例中,我呈现了几个选项卡。一个新的选项卡最初显示一个DB“表”名称的列表(这个示例是固定的)。在选择表名时,列表将被表的内容替换。

问题是当您关闭打开的选项卡时,currentTab状态不会更新到我要设置的(打开)选项卡。由于该选项卡的详细区域仍然是空白的,直到我手动单击打开的选项卡的名称。

在上面的图片中,我关闭了第三个选项卡。期望选项卡选择应该自动更改为第二个选项卡,但它没有。同样的代码如下所示。
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]);
}
}
}通过的id上方是第三个选项卡。tabsList状态包含一个数组,其中包含每个选项卡的数据。currentTab只包含当前选项卡的id。按照上面的console.log语句,将传递正确的选项卡的id,但是currentTab从不更新。即使我把代码写在下面。
useEffect(() => { console.log('------------>', currentTab) }, [currentTab]);在这种情况下它从不开火。
removeTab方法是从JSX调用的,如下所示。
{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>
))}发布于 2022-11-26 16:49:10
有两个问题
这是我对代码框https://codesandbox.io/s/practical-platform-dvkxrq?file=/src/Tabs.js:3723-3738所做的编辑。
发布于 2022-11-26 17:46:46
我对代码做了一些修改,它们可能会帮助您找到更好的解决方案。
将初始值选项卡设置为状态,而不是useEffect、减少呈现周期
删除和添加创建一个新数组
你可以找到修改代码框示例
使用单个选定项呈现内容防止重复
唯一的问题是反应不是刷新删除上的更改,所以我不得不使用黑客,在这种情况下,您可能会发现这是有帮助的。
let tabId = 1;
const DisplayTable = ({ isNewMode, name, ...rest }) => {
return (
<div>
{isNewMode ? (
<TableSelection {...rest} />
) : (
<div>Contents of table: {name}</div>
)}
</div>
);
};
export default function Tabs() {
const [tabsList, setTabsList] = useState([
{
id: tabId,
name: "Select table",
isNewMode: true
}
]);
const [currentTab, setCurrentTab] = useState(tabId);
function newTab() {
tabId = tabId + 1; // unique id check
return {
id: tabId,
name: "Select table",
isNewMode: true
};
}
function addTab() {
const t = newTab();
setTabsList((tabs) => [...tabs, t]);
console.log("++++++3", t, t.id);
setCurrentTab(t.id);
}
async function removeTab(id) {
// functional updaters are simpler
// setTabsList(tabs => [...tabs.filter((a) => a.id !== id)])
// need better logic to select the right tab, this seems simeple enough to understand
const deleteIndex = tabsList.findIndex((v) => v.id === id);
//
if (deleteIndex !== -1) {
const filteredItems = tabsList.filter((a) => a.id !== id);
if (deleteIndex > 0) {
const prevId = filteredItems[deleteIndex - 1];
console.log("prevId", prevId);
setTabsList([...filteredItems]);
await Promise.resolve();
setCurrentTab(prevId.id);
}
}
}
const selectedItem = tabsList?.find((item) => item.id === currentTab);
// console.log("Rendering......", currentTab, tabsList);
return (
<div className="p-8 h-full flex flex-col">
<div className="tabs">
{tabsList.map((t) => (
<a
href="#"
key={t.id}
className={
"tab tab-bordered " + (currentTab === t.id ? "tab-active" : "")
}
onClick={(e) => {
e.preventDefault();
setCurrentTab(t.id);
}}
>
{t.name}
<button
className="ml-2 btn btn-ghost btn-square btn-xs"
onClick={(e) => {
e.preventDefault();
removeTab(t.id);
}}
>
X
</button>
</a>
))}
<a href="#" className="tab">
<button
className="btn btn-ghost btn-square btn-xs"
onClick={(e) => {
e.preventDefault();
addTab();
}}
>
+
</button>
</a>
</div>
{selectedItem ? (
<DisplayTable
onTableSelection={(item) => {
tabId = tabId + 1;
const d = { ...item, id: tabId, isNewMode: false };
setTabsList((t) => [...t, d]);
console.log("table select", d);
setCurrentTab(d.id);
}}
{...selectedItem}
/>
) : null}
{/* {tabsList.map((t) => (
<div key={t.id}>
<TableSelection />
</div>
))} */}
</div>
);
}希望在某种程度上是有用的,
干杯
https://stackoverflow.com/questions/74583787
复制相似问题