setTimeout
関数を使用すると、reactコンポーネントが無限のconsole.logを開始する理由がわかりません。すべてが機能しているが、PCは地獄のように遅れ始める。私の状態を変更するタイムアウトで機能し、そのコンポーネントを再レンダリングし、新しいタイマーを設定するなどと言う人もいます。今、私はそれが正しいことをクリアする方法を理解する必要があります。
export default function Loading() {
// if data fetching is slow, after 1 sec i will show some loading animation
const [showLoading, setShowLoading] = useState(true)
let timer1 = setTimeout(() => setShowLoading(true), 1000)
console.log('this message will render every second')
return 1
}
異なるバージョンのコードで次のことを助けていないことを明確にします。
const [showLoading, setShowLoading] = useState(true)
let timer1 = setTimeout(() => setShowLoading(true), 1000)
useEffect(
() => {
return () => {
clearTimeout(timer1)
}
},
[showLoading]
)
useEffect
のReturn関数は、useEffect
が実行されるたびに実行されます(コンポーネントマウントでの最初の実行を除く)。新しいuseEffect
が実行されるたびに、古い実行が削除されるため、それについて考えてください。
export default function Loading() {
const [showLoading, setShowLoading] = useState(false)
useEffect(
() => {
let timer1 = setTimeout(() => setShowLoading(true), 1000)
// this will clear Timeout when component unmont like in willComponentUnmount
return () => {
clearTimeout(timer1)
}
},
[] //useEffect will run only one time
//if you pass a value to array, like this [data] than clearTimeout will run every time this value changes (useEffect re-run)
)
return showLoading && <div>I will be visible after ~1000ms</div>
}
export default function Loading() {
const [showLoading, setShowLoading] = useState(false)
const timerToClearSomewhere = useRef(false) //now you can pass timer to another component
useEffect(
() => {
timerToClearSomewhere.current = setInterval(() => setShowLoading(true), 1000)
return () => {
clearInterval(timerToClearSomewhere.current)
}
},
[]
)
//here we can imitate clear from somewhere else place
useEffect(() => {
setTimeout(() => clearInterval(timerToClearSomewhere.current), 15000)
}, [])
return showLoading && <div>I will be visible after ~1000ms</div>
}
キューを管理する必要がある場合(タイマー/インターバル内の状態を変更する)、 ここで答えを探してください
useEffect
の2番目の引数として空の配列を渡すのを忘れて、コールバック内でsetState
をトリガーしていたため、コンピューターが遅れていました。 useEffect
がレンダリングでトリガーされるため、無限ループが発生します。
以下は、マウント時にタイマーを設定し、アンマウント時にタイマーをクリアする有効な方法です。
function App() {
React.useEffect(() => {
const timer = window.setInterval(() => {
console.log('1 second has passed');
}, 1000);
return () => { // Return callback to run on unmount.
window.clearInterval(timer);
};
}, []); // Pass in empty array to run useEffect only on mount.
return (
<div>
Timer Example
</div>
);
}
ReactDOM.render(
<div>
<App />
</div>,
document.querySelector("#app")
);
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>