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

Javascript 如何在React原生应用程序中使用React hook useEffect设置每5秒渲染的间隔?,javascript,react-native,setinterval,react-hooks,use-effect,Javascript,React Native,Setinterval,React Hooks,Use Effect,我有React Native应用程序,我通过fetch从API获取数据。我创建了从API获取数据的自定义钩子。我需要每5秒重新渲染一次。为此,我将我的自定义钩子包装到setInterval,在我的应用程序变得工作非常缓慢之后,当我导航到另一个屏幕时,我得到以下错误: 无法对未安装的组件执行React状态更新。这是 无操作,但表示应用程序内存泄漏。要解决, 取消useEffect清理中的所有订阅和异步任务 功能 您能告诉我如何解决这个错误,以及哪种方法是设置间隔的最佳方法,因为我认为我的方法不好

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


无法对未安装的组件执行React状态更新。这是 无操作,但表示应用程序内存泄漏。要解决, 取消useEffect清理中的所有订阅和异步任务 功能

您能告诉我如何解决这个错误,以及哪种方法是设置间隔的最佳方法,因为我认为我的方法不好

我的自定义挂钩:

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

我的组件:

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

const chartscreen=({navigation})=>{
常量{container}=样式
常量url=https://poloniex.com/public?command=returnTicker'
const{data,错误,正在加载}=useFetch(url)
const percentColorHandler=number=>{
返回编号>=0?真:假
}
返回(
导航。导航('Welcome')}
/>
item.key}
renderItem={({item})=>(
)}
/>
)
}

您需要清除
间隔

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
函数的更多信息,请参阅。

可能是以下两种情况:

  • 你需要整理一下你的休息时间
  • 如果API回调已卸载,则不需要从API回调更新状态
代码:


根据您的服务器响应时间,您可能希望为挂起的查询添加故障保护(例如,如果您发送了一个查询,并且在第一个查询返回之前启动了下一个查询…)

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


我添加了这两行,但无论如何都有一个错误,应用程序运行非常缓慢。错误是什么?由于设置间隔时间,应用程序运行缓慢,每次都会等待5秒。尝试缩短时间。无法对未安装的组件执行React状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。若要修复此问题,请取消useEffect清理函数中的所有订阅和异步任务。您的应用程序中是否有其他setInterval?通过这样做
return()=>clearInterval(intervalId)它将清除setInterval。因为我想用于卸载组件。我删除了它,现在效果更好了。非常感谢你。请再告诉我一件事,这个组件在我的tabsNavigator的一个选项卡中呈现,当我更改选项卡组件没有卸载时,呈现仍在工作。只有当我离开导航堆栈时,组件才会卸载。为什么?错误仍然在出现,但不像以前那样频繁