如何在 React Native 应用程序中使用 React hook useEffect 每 5 秒渲染一次设置间隔?

新手上路,请多包涵

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

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请在 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>
  )
}

原文由 jocoders 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 286
1 个回答

您需要清除您的 interval

 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])

有关 cleanupuseEffect --- 中的功能的更多信息,请参阅

原文由 ravibagul91 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题