当前位置: 首页 > 知识库问答 >
问题:

如何在React原生应用程序中使用React hook useEffect设置每5秒渲染的间隔?

谢骏奇
2023-03-14

我有React Native应用程序,我通过fetchAPI获取数据。我创建了从API获取数据的自定义钩子。我需要每5秒重新渲染一次。为此,我将我的自定义钩子包装到setInterval,在我的应用程序变得工作非常缓慢之后,当我导航到另一个屏幕时,我得到以下错误:

无法对未安装的组件执行React状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。要修复此问题,请取消useEffect清理函数中的所有订阅和异步任务。

你能告诉我,请如何解决这个错误,这将是最好的方式setInterval,因为我认为我的方式不好。

我的定制挂钩:

export const useFetch = url => {
  const [state, setState] = useState({ data: null, error: false, loading: true })

  useEffect(() => {
    setInterval(() => {
      setState(state => ({ data: state.data, error: false, loading: true }))
      fetch(url)
        .then(data => data.json())
        .then(obj =>
          Object.keys(obj).map(key => {
            let newData = obj[key]
            newData.key = key
            return newData
          })
        )
        .then(newData => setState({ data: newData, error: false, loading: false }))
        .catch(function(error) {
          console.log(error)
          setState({ data: null, error: true, loading: false })
        })
    }, 5000)
  }, [url, useState])
  useEffect(() => () => console.log('unmount'), [])
  return state
}

我的组成部分:

const ChartsScreen = ({ navigation }) => {
  const { container } = styles
  const url = 'https://poloniex.com/public?command=returnTicker'
  const { data, error, loading } = useFetch(url)

  const percentColorHandler = number => {
    return number >= 0 ? true : false
  }

  return (
    <View style={container}>
      <ProjectStatusBar />
      <IconsHeader
        dataError={false}
        header="Charts"
        leftIconName="ios-arrow-back"
        leftIconPress={() => navigation.navigate('Welcome')}
      />
      <ChartsHeader />
      <ActivityIndicator animating={loading} color="#068485" style={{ top: HP('30%') }} size="small" />
      <FlatList
        data={data}
        keyExtractor={item => item.key}
        renderItem={({ item }) => (
          <CryptoItem
            name={item.key}
            highBid={item.highestBid}
            lastBid={item.last}
            percent={item.percentChange}
            percentColor={percentColorHandler(item.percentChange)}
          />
        )}
      />
    </View>
  )
}

共有3个答案

韶镜
2023-03-14

React Hooks Apollo每5秒从GraphQL服务器获取数据。在本例中,如果用户未在后端登录,我们将在React中注销该用户。(JWT令牌不再有效)

import React from 'react'
import gql from 'graphql-tag'
import { useApolloClient } from '@apollo/react-hooks'

export const QUERY = gql`
  query Me {
    me {
      id
    }
  }
`

const MyIdle = () => {
  const client = useApolloClient()

  React.useEffect(() => {
    async function fetchMyAPI() {
      try {
        await client.query({
          query: QUERY,
          fetchPolicy: 'no-cache',
        })
      } catch (e) {
        // Logout the user and redirect to the login page
      }
    }

    const intervalId = setInterval(() => {
      fetchMyAPI()
    }, 1000 * 5) // in milliseconds
    return () => clearInterval(intervalId)
  }, [client])

  return null
}
export default MyIdle

潘俊楚
2023-03-14

可能是这两种情况:

  • 你需要理清你的时间间隔
  • 如果API回调已卸载,则不需要从API回调更新状态

代码:

useEffect(() => {
   let isMounted = true
   const intervalId = setInterval(() => {  //assign interval to a variaable to clear it
    setState(state => ({ data: state.data, error: false, loading: true }))
    fetch(url)
      .then(data => data.json())
      .then(obj =>
        Object.keys(obj).map(key => {
          let newData = obj[key]
          newData.key = key
          return newData
        })
     )
     .then(newData => {
        if(!isMounted) return  // This will cancel the setState when unmounted
        setState({ data: newData, error: false, loading: false })
     })
     .catch(function(error) {
        console.log(error)
        setState({ data: null, error: true, loading: false })
     })
   }, 5000)

   return () => {
       clearInterval(intervalId); //This is important
       isMounted = false // Let's us know the component is no longer mounted.
   }

}, [url, useState])

根据您的服务器响应时间,可能需要为挂起的查询添加故障保险(例如,如果您发送了一个查询,而下一个查询在第一个查询返回之前启动...)。

南门欣怡
2023-03-14

你需要清除你的间隔

useEffect(() => {
  const intervalId = setInterval(() => {  //assign interval to a variable to clear it.
    setState(state => ({ data: state.data, error: false, loading: true }))
    fetch(url)
      .then(data => data.json())
      .then(obj =>
        Object.keys(obj).map(key => {
          let newData = obj[key]
          newData.key = key
          return newData
        })
     )
     .then(newData => setState({ data: newData, error: false, loading: false }))
     .catch(function(error) {
        console.log(error)
        setState({ data: null, error: true, loading: false })
     })
  }, 5000)

  return () => clearInterval(intervalId); //This is important
 
}, [url, useState])

有关useffect中的cleanup功能的更多信息,请参阅此。

 类似资料:
  • 问题内容: 我有一个swing应用程序,该应用程序将命令发送到服务器并接收XML格式的结果。我需要通过XSLT将其转换为HTML,然后在面板上显示结果HTML。问题在于,唯一能够显示HTML的Swing组件- JEditorPane- 将URL或javax.swing.text.StyledDocument用作源。带有URL的选项对我不起作用,因为我必须先将html作为文件保存在文件系统中,并且我

  • 问题内容: 我正在阅读面向Python开发人员的Matplotlib书,但正在努力遵循第8章“ Django应用程序中的Matplotlib”部分中的示例。 到目前为止,我已经发出了命令 然后在目录中 按照示例,我做了如下: 接下来,这本书说应当在其中添加以下行: 但是,我看不到它如何工作,因为在’default’中,有很多对象: 并且没有定义构造函数。也许这本书(来自2009年)指的是旧版Dja

  • 因此,我正在创建一个React本机应用程序,我想从应用程序的本机部分调用JavaScript函数。 我知道我可以使用Native模块在Native和React Native之间建立一座桥梁,我还知道从Native模块我可以发出React Native可以接收的事件。 但是,本机模块内的任何函数调用只能从React本机本身内部发生,因为它需要一个React本机上下文,因此我只能在React本机本身调

  • 我有一个用Kotlin(android studio)编写的android应用程序和用React Native编写的应用程序的UI。我的问题是这些能联系在一起吗?如果是,怎么做?还有,你们能发布一些我可以通过的链接吗。 附注:我对react Native一无所知。

  • 问题内容: 在pyGame应用程序中,我想呈现SVG中描述的无分辨率的GUI小部件。 我可以使用什么工具和/或库来实现此目标? (我喜欢OCEMP GUI工具箱,但它的呈现似乎取决于位图) 问题答案: 这是一个完整的示例,其中结合了其他人的提示。它应该从当前目录渲染一个名为test.svg的文件。它已在Ubuntu 10.10,python-cairo 1.8.8,python-pygame 1.

  • 我正试图在Android设备上运行我的应用程序:AmazonFireTV。 此构建可能会更快,请考虑使用Gradle守护进程:https://docs.Gradle.org/2.14.1/userguide/gradle_daemon.html Running/users/xxxx/library/android/sdk//platform-tools/adb-s 68.128.177.159:5