我有一個反應原生的待辦事項串列應用程式。任務項由一個使用 useState 的陣串列示,宣告如下:
const [taskItems, setTaskItems] = useState([]);
我正在嘗試添加一個洗掉所有專案的函式,而不是像這樣設定它setTaskItems([]),它只是一次洗掉所有專案,我希望從最后開始一次洗掉一個專案以創建更多影片外觀。
while(taskItems.length > 0)
{
alert(taskItems.length);
let itemsCopy = [...taskItems];
itemsCopy.splice(-1);
setTaskItems(itemsCopy);
//setTimeout(function(){},180);
}
由于某種原因,上面的代碼會導致無限遞回。如果我洗掉了 while 回圈,那么deleteAll函式確實會洗掉串列中的最后一項。根據我將警報放在函式的開頭,陣列的長度似乎永遠不會減少。
這是為什么?
有沒有更好的方法來達到這種效果?
uj5u.com熱心網友回復:
發生這種情況是因為您的代碼taskItem值在您使用時不會改變setTaskItems
setTaskItems是一個異步函式,組件重新渲染后 state 屬性的更新值發生變化
你可以試試這樣的
const [taskItems, setTaskItems] = useState([]);
const [deleteAll, setDeleteAll] = useState(false)
useEffect(() => {
if(!deleteAll) return;
if(taskItems.lenght === 0){
setDeleteAll(false)
return;
}
setTimeout(() => {
setTaskItems(t => t.slice(0, -1))
}, 180)
}, [deleteAll, taskItems])
const handleDeleteAll = () => {
seDeleteAll(true)
}
uj5u.com熱心網友回復:
這是因為taskItems值是從閉包中檢索的,這意味著您不能期望在處理程式執行期間更改值。閉包僅在元素重新渲染后重新創建,這意味著您只能在下一個函式執行時訪問新的狀態值 - 在函式執行期間狀態的值永遠不會改變。
您只需將長度值分配給某個臨時變數,并將其用作 while 回圈的開始/停止指示器:
let itemsCount = taskItems.length;
while(itemsCount > 0)
{
// Here use itemsCount to determine how much you would need to slice taskItems array
itemsCount -= 1;
}
更新
你應該如何做的一個想法是:
const [items, setItems] = useState([1, 2, 3, 4, 5]);
const deleteAll = () => {
let counter = items.length;
while (counter > 0) {
setTimeout(() => {
setItems((p) => [...p.slice(0, counter - 1)]);
}, counter * 1000);
counter -= 1;
}
};
將超時延遲與長度相乘很重要,以避免同時執行所有超時-您需要一一洗掉。此外,您應該清除卸載超時或類似的東西。
uj5u.com熱心網友回復:
由于 React useState hook 的異步特性,你需要利用 useEffect 來完成這項作業。這是洗掉專案之間有 1000 毫秒延遲的所有任務的作業示例。
function TasksGrid() {
const [taskItems, setTaskItems] = useState([1, 2, 3, 4, 5, 6]);
const [runDeleteAll, setRunDeleteAll] = useState(false);
useEffect(
() => {
if (runDeleteAll) {
if (taskItems.length > 0)
setTimeout(() => setTaskItems(taskItems.slice(0, taskItems.length - 1)), 1000);
else
setRunDeleteAll(false);
}
},
[runDeleteAll, taskItems]
)
const handleOnClick = () => {
setRunDeleteAll(true);
}
return (
<div>
{taskItems.map((taskItem, idx) => <p key={idx}>task {taskItem}</p>)}
<button onClick={handleOnClick}>delete all</button>
</div>
);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/497199.html
標籤:javascript 反应 反应式
