重い処理と軽い処理が混在するケースで、いい感じにローディングを表示させたいが、処理が早い場合、ローディングがチラついてしまう。
処理が早すぎる場合を考慮して、1000ms(1秒) - 実行時間
表示を遅延させ、1000ms以上
実行時間がある場合は、遅延時間0ms
にする。
const [isLoading, setIsLoading] = useState(false) const handleUpdate = () => { setIsLoading(true) // ローディング状態にする const startTime = new Date().getTime() // 計測開始時間 dispatch(update()) .then(() => {}) .catch(() => {}) .finally(() => { const currentTime = new Date().getTime() // 計測終了時間 const executionTime = currentTime - startTime // 実行時間 const delayTime = 1000 - executionTime // 表示を遅延させる時間 // ローディング状態を解除する setTimeout(() => setIsLoading(false), Math.max(delayTime, 0)) }) }
setTimeout(() => setIsLoading(false), Math.max(1000 - (currentTime - startTime), 0))
凝縮性
javascript-useStatesetメソッドは変更をすぐには反映しません-StackOverflow
import { useState } from 'react' export const useLoading = () => { const [isLoading, setIsLoading] = useState(false) let startTime = 0 const startLoading = () => { setIsLoading(true) startTime = new Date().getTime() } /** * ローディングを終了する * @param minWaitTime ローディングが完了するまでの最小待ち時間 */ const endLoading = (minWaitTime: number = 1000) => { const currentTime = new Date().getTime() const executionTime = currentTime - startTime const delayTime = minWaitTime - executionTime setTimeout(() => { setIsLoading(false) startTime = 0 }, Math.max(delayTime, 0)) } return { isLoading, startLoading, endLoading } }
実行時間が1000ms以下の場合、delayTime
は、0 ~ 999
の値になる。
実行時間が1000ms以上の場合、delayTime
は、-(マイナス)
になるので、Math.max(delayTime, 0))
で0が返され、遅延時間が0msになる。