我正在構建一個函式,使隨機汽車的影像在螢屏上具有影片效果,并且我想用 setTimeout 錯開“carsLeft”陣列的數量..(我最終將隨機化延遲時間)。
一切正常,直到我嘗試使用 setTimeout。使用下面的代碼,沒有顯示任何汽車。Console.log 顯示“carsLeft”陣列未填充。當我洗掉 setTimeout 時,所有汽車都會顯示出來(當然是一次性的)。我試過 IIDE 仍然沒有運氣。被這個卡住了一段時間,請幫忙!
function Traffic() {
let carsLeft: any = [];
const generateCarLeft = () => {
for (let i = 0; i < 5; i ) {
setTimeout(() => {
carsLeft.push(
<CarLeft key={i} className="car__left">
<img
src={carListDay[Math.floor(Math.random() * carListDay.length)]}
alt=""
/>
</CarLeft>
);
}, 3000);
}
};
generateCarLeft();
return <div className="traffic__container">{carsLeft}</div>;
}
export default Traffic;
uj5u.com熱心網友回復:
如果要通過回圈生成元素并在組件安裝后發生,則使用React.useEffect鉤子,例如
React.useEffect(() => {
generateCarsLeft()
}, [])
并且使用carsLeft作為狀態將解決問題。
uj5u.com熱心網友回復:
如果沒有 state 和 setTimeout 它會起作用,因為在第一次渲染(掛載)之前所有資料都可用。
但是如果你在第一個渲染串列中使用是空的,并且在 setTimeout 之后它會更新變數但反應不知道變數被更新你必須使用狀態來解決這個問題。
function Traffic() {
const [carsLeft, setCarsLeft] = useState([]);
const generateCarLeft = () => {
for (let i = 0; i < 5; i ) {
setTimeout(() => {
setCarsLeft((items) => [
...items,
<CarLeft key={i} className="car__left">
<img
src={carListDay[Math.floor(Math.random() * carListDay.length)]}
alt=""
/>
</CarLeft>,
]);
}, 3000);
}
};
generateCarLeft();
return <div className="traffic__container">{carsLeft}</div>;
}
uj5u.com熱心網友回復:
React 組件本質上只是一個函式,因此如果您在該函式中宣告一個變數,則每次呼叫它時都會重新創建它。如果您希望在呼叫之間保留任何值,則必須將其保存在其他地方。在 React 中,“某處”就是狀態。
除非 React 檢測到狀態的變化,否則它甚至不會重新渲染組件。
所以現在你的組件被呼叫一次,3 秒后所有 5 個新元素都被一次添加到陣列中,但是組件沒有重新渲染,因為 React 沒有跟蹤這個變化。我會給你一個例子來說明它是如何作業的,但我建議你更多地了解 React 的狀態和生命周期概念。
function Traffic() {
[carsLeft, setCarsLeft] = React.useState([]);
React.useEffect(()=>{
if(carsLeft.length > 4) return;
setTimeout(() => {
setCarsLeft( cl => [...cl,
<CarLeft key={i} className="car__left">
<img
src={carListDay[Math.floor(Math.random() * carListDay.length)]}
alt=""/>]
);
}, 3000);
})
return <div className="traffic__container">{carsLeft}</div>;
}
uj5u.com熱心網友回復:
這就是你要找的
const list = ["Hello", "how", "are", "you"];
function App() {
const [myList, updateList] = useState([])
useEffect(() =>{
for (let i=0; i<list.length; i ) {
setTimeout(() => {
updateList((prvList) => ([...prvList, list[i]]));
}, 1000 * i) // * i is important
}
}, []);
return (
<div>
{
myList.map(li => (<div key={li}>{li}</div>))
}
</div>
);
}
uj5u.com熱心網友回復:
即使這確實運行了,它也不會按照您希望的方式運行。由于for回圈速度極快,您需要等待 3 秒才能一次獲得 5 輛車。
你需要擺脫回圈。并且您需要將所有副作用包裝在一個useEffect鉤子中,并將所有持久變數包裝carsLeft在一個useState鉤子中。
export default function Traffic() {
const [carsLeft, setCarsLeft] = useState<Array<ReactNode>>([]);
const timeout = useRef<number>();
useEffect(() => {
timeout.current = setTimeout(() => {
if (carsLeft.length < 5)
setCarsLeft([
...carsLeft,
<CarLeft key={carsLeft.length} className="car__left">
<img
src={carListDay[Math.floor(Math.random() * carListDay.length)]}
alt=""
/>
</CarLeft>
]);
else clearTimeout(timeout.current);
}, 3000);
return () => {
clearTimeout(timeout.current);
};
}, [carsLeft]);
return <div className="traffic__container">{carsLeft}</div>;
}
Codesandbox 演示:https ://codesandbox.io/s/naughty-driscoll-6k6u8 ? file =/ src/App.tsx
uj5u.com熱心網友回復:
我已經解決了所有問題,并且一切正常。我使用 @Summer 的方法來洗掉 for 回圈,讓 useEffect State 更改創建自己的無限回圈。我使用了 setInterval 方法而不是 setTimeout。我在 Summer 的解決方案中遇到的一個問題是使用“carsOnTheLeft.length”來生成鍵值。這導致多個鍵具有相同的值并導致一些問題。為了解決這個問題,我創建了一個新的狀態“carLeftIndex”來在每次重新渲染時生成一個唯一的鍵。由于 React 的“onAnimationEnd()”觸發了“handleRemoveItem”函式,當影片完成時,生成的物件會從狀態陣列中移除。這是我的作業代碼,感謝您的回答!
const getRandomNumber = (min: number, max: number) => {
return Math.random() * (max - min) min;
};
const carListDay = [car_1, car_2, car_3, car_4, car_5, car_6];
function Traffic() {
const [carsOnTheLeft, setCarsOnTheLeft] = useState<any>([]);
const timeout = useRef<any>();
const [carLeftIndex, setCarLeftIndex] = useState(0);
useEffect(() => {
const getRandomNumberToString = (min: number, max: number) => {
const result = Math.random() * (max - min) min;
return result.toString();
};
setCarLeftIndex(carLeftIndex 1);
const CarLeft = styled.div`
animation-duration: ${getRandomNumberToString(3, 10)}s;
`;
timeout.current = setInterval(() => {
getRandomNumberToString(2, 9);
if (carsOnTheLeft.length < 15)
setCarsOnTheLeft([
...carsOnTheLeft,
<CarLeft
key={carLeftIndex}
className="car__left"
onAnimationEnd={(e) => handleRemoveItem(e)}
>
<img
src={carListDay[Math.floor(Math.random() * carListDay.length)]}
alt=""
/>
</CarLeft>,
]);
else clearTimeout(timeout.current);
}, getRandomNumber(100, 5000));
console.log(carsOnTheLeft);
console.log(carLeftIndex);
const handleRemoveItem = (e: any) => {
setCarsOnTheLeft((carsOnTheLeft: any) =>
carsOnTheLeft.filter((key: any, i: any) => i !== 0)
);
};
return () => {
clearTimeout(timeout.current);
};
}, [carsOnTheLeft]);
return <div className="traffic__container">{carsOnTheLeft}</div>;
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/399152.html
下一篇:將長代碼撰寫為嵌套串列理解
