3 回答

TA貢獻1772條經驗 獲得超5個贊
讓您的組件在索引更改時由其狀態驅動,它會觸發更新 currentFruit 狀態的 useEffect 掛鉤,currentFruit 更改會觸發另一個更新索引的 useEffect 等等,然后只需使用 like setTimeout:
const IntervalExample = () => {
const fruits = [
{id: 1, name: "Orange", duration: 2000},
{id: 2, name: "Kiwi", duration: 1000},
{id: 3, name: "Mango", duration: 3000},
]
const [index, setIndex] = useState(0);
const [currentFruit, setCurrentFruit] = useState(fruits[index]);
useEffect(() => {
setCurrentFruit(fruits[index])
}, [index])
useEffect(() => {
const interval = setTimeout(() => {
setIndex(index === fruits.length - 1 ? 0 : index + 1)
}, currentFruit.duration);
}, [currentFruit])
return (
<div className="App">
<header className="App-header">
{currentFruit.name}: {currentFruit.duration}
</header>
</div>
);
};

TA貢獻1802條經驗 獲得超4個贊
UseEffect 只被調用一次。因此,Const interval將為時間間隔的函數調用初始化一個閉包。它永遠不會改變。關閉中的索引將始終為 0。
這是我的解決方案,只需使用一種狀態作為索引:
const IntervalExample = () => {
const fruits = [
{id: 1, name: "Orange", duration: 2000},
{id: 2, name: "Kiwi", duration: 1000},
{id: 3, name: "Mango", duration: 3000},
]
const [index, setIndex] = useState(0);
//because fruit depend on index. Dont need a separate state
const currentFruit = fruits[index];
const handleIndex = () => {
setIndex(index === fruits.length - 1 ? 0 : index + 1)
}
useEffect(() => {
//after render current fruit. We new timeout to set next fruit.
setTimeout(handleIndex, currentFruit.duration);
}, [index]);
return (
<div className="App">
<header className="App-header">
{currentFruit.name}: {currentFruit.duration}
</header>
</div>
);
};

TA貢獻1796條經驗 獲得超4個贊
如果你想為每個水果使用不同的超時,那setTimeout將是更好的方法。
由于在初始值setInterval被調用時會被設置為改變顯示水果信息的時間間隔。useEffect
您的代碼中的問題是在更新index狀態時未正確更新。
為了解決這個問題而不是直接更新值,我使用更新后的狀態值,如下所示
setIndex((index) => (index === fruits.length - 1 ? 0 : index + 1))
const { useState, useEffect } = React;
const fruits = [
{ id: 1, name: "Orange", duration: 2000 },
{ id: 2, name: "Kiwi", duration: 1000 },
{ id: 3, name: "Mango", duration: 3000 }
];
const IntervalExample = () => {
const [index, setIndex] = useState(0);
const [currentFruit, setCurrentFruit] = useState(fruits[0]);
useEffect(() => {
const interval = setInterval(() => {
setIndex((index) => (index === fruits.length - 1 ? 0 : index + 1));
}, fruits[index].duration);
return () => clearInterval(interval);
}, []);
useEffect(() => {
setCurrentFruit(fruits[index]);
}, [index]);
return (
<div className="App">
<header className="App-header">
{currentFruit.name}: {currentFruit.duration}
</header>
</div>
);
};
ReactDOM.render(
<IntervalExample />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
添加回答
舉報