React实现模拟数字进度条

417 阅读1分钟

实际项目中有些时候接口要很久返回,接口又不能给你返回正确进度,只能前端自己模拟实现,--- 作用于最近chatgat 生成图片、调用接口返回等待

增加useSimulateProgress hooks

import { useEffect, useRef, useState } from 'react'

export default function useSimulateProgress (defaultValue = 0) {
  // const [progressVal, setProgressVal] = useState(defaultValue)
  const [count, setCount] = useState(defaultValue)
  const progressVal = useRef(defaultValue)
  const r = useRef()
  const i = (u, l = 1, f = null) => {
    r.current && cancelAnimationFrame(r.current)
    const p = () => {
      // eslint-disable-next-line one-var
      let d = !1,
        h = progressVal.current
      // eslint-disable-next-line no-unused-expressions
      Math.abs(u - progressVal.current) < l ? (h = u,
      d = !0) : u > progressVal.current ? h += l : h -= l,
      h = Math.min(100, Math.max(0, h)),
      progressVal.current = h,
      setCount(h),
      progressVal.current === 100 && f && f(),
      !d && (r.current = requestAnimationFrame(p))
    }

    r.current = requestAnimationFrame(p)
  }

  useEffect(() => {
    const timer = setInterval(() => {
      let u = 100
      let f = u - progressVal.current
      let p = Math.random() * f / 4
      let d = Math.min(progressVal.current + p, u * 0.97)
      i(d, 1)
    }, 1000)

    return () => {
      clearInterval(timer)
      r.current && cancelAnimationFrame(r.current)
    }
  }, [])

  return [count]
}

调用js的方法

import React from 'react'
import useSimulateProgress from '@utils/useSimulateProgress'

export default function ContentLoading ({ status }) {
  const [progressVal] = useSimulateProgress()

  return <div>
    {Math.floor(progressVal)}%
  </div>
}