使用计时器管理 API 调用的 React 钩子 [英] React hooks to manage API call with a timer

查看:20
本文介绍了使用计时器管理 API 调用的 React 钩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要执行一个返回 URL 的 fetch API 调用,对返回的 URL 执行某些操作,然后在 60 秒后刷新 URL.这是我可以在没有钩子的情况下轻松实现的目标,但我想要一个钩子解决方案.

I need to do a fetch API call that returns a URL, do something with the returned URL, then refresh the URL after 60 seconds. This is something I could comfortably achieve without hooks, but I'd like a hooks solution.

重要提示:我不打算将其重构为多个组件,或者为计时器或 API 调用创建自定义挂钩.

IMPORTANT: I'm not looking to refactor this to multiple components, or create custom hooks for either the timer or API call.

编辑:问题是 - 这是在钩子环境中处理计时器的正确方法吗?有没有更好的办法?

EDIT: The question is - is this the correct way to handle a timer in a hooks environment? Is there a better way?

import React, { useState, useEffect } from 'react'
import { post } from 'utils/requests'

const FetchUrl = ({ id }) => {
  const [url, setUrl] = useState('')
  let [count, setCount] = useState(0)

  const tick = () => {
    let newCount = count < 60 ? count + 1 : 0
    setCount(newCount)
  }

  useEffect(() => {
    const timer = setInterval(() => tick(), 1000)

    if (count === 0) {
      post('/api/return-url/', { id: [id] })
        .then(res => {
          if (res && res.content) {
            setUrl(res.content.url)
          }
        })
    }

    return () => clearInterval(timer)
  })

  return url ? (
    <span className="btn sm">
      <a href={url} target="_blank" rel="noopener noreferrer">go</a>
    </span>
  ) : null
}

export default FetchUrl

推荐答案

看看这是否适合你.

我会将其分为 2 个useEffect().一个在第一次渲染后运行(类似于 componentDidMount)来设置计时器.以及其他根据计数值进行API调用.

I would divide that into 2 useEffect(). One to run after 1st render (similar to componentDidMount) to set the timer. And other to make the API call based on the count value.

注意:我使用 ref 只是为了区分一个 API 调用与另一个调用并添加一个数字.

Note: I used the ref just so I could differentiate one API call from another and add a number to it.

见下面的片段:

const FetchUrl = ({ id }) => {
  const [url, setUrl] = React.useState('');
  const [count, setCount] = React.useState(0);
  const someRef = React.useRef(0);

  const tick = () => {
    //let newCount = count < 60 ? count + 1 : 0
    setCount((prevState) => prevState < 60 ? prevState +1 : 0);
  }
  
  function mockAPI() {
    return new Promise((resolve,request) => {
      someRef.current = someRef.current + 1;
      setTimeout(()=>resolve('newData from API call ' + someRef.current),1000);
    });
  }

  React.useEffect(() => {
    const timer = setInterval(() => tick(), 100);
    return () => clearInterval(timer);
  });
  
  React.useEffect(() => {
    if (count === 0) {
      /*post('/api/return-url/', { id: [id] })
        .then(res => {
          if (res && res.content) {
            setUrl(res.content.url)
          }
        })
      */
      mockAPI().then((data) => setUrl(data));
    }
  },[count]);

  return url ? (
    <span className="btn sm">
      <div>{count}</div>
      <a href={url} target="_blank" rel="noopener noreferrer">{url}</a>
    </span>
  ) : null
}

ReactDOM.render(<FetchUrl/>, document.getElementById('root'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

这篇关于使用计时器管理 API 调用的 React 钩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆