[英]How to setInterval for every 5 second render with React hook useEffect in React Native app?
I have React Native
app and I get data from API
by fetch
.我有
React Native
应用程序,我通过fetch
从API
获取数据。 I created custom hook that get data from API
.我创建了从
API
获取数据的自定义钩子。 And i need to re-render it every 5 seconds.我需要每 5 秒重新渲染一次。 For it I wrapped my custom hook to setInterval and after my app become work very slowly and when I navigate to another screen I get this error:
为此,我将我的自定义钩子包装到 setInterval 并且在我的应用程序变得非常缓慢并且当我导航到另一个屏幕时我收到此错误:
Can't perform a React state update on an unmounted component.
无法对卸载的组件执行 React 状态更新。 This is a no-op, but it indicates a memory leak in your application.
这是一个空操作,但它表明您的应用程序中存在内存泄漏。 To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。
Can you tell me please how can I solve this bug and which will be the best way to setInterval
, because I think my way is not good.你能告诉我如何解决这个错误,哪种是最好的
setInterval
,因为我认为我的方法不好。
My custom hook:我的自定义钩子:
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
}
My Component:我的组件:
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>
)
}
You need to clear your interval
,你需要清除你的
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])
For more about cleanup
functions in useEffect
refer to this .有关
useEffect
cleanup
功能的更多信息,请参阅此。
It might be both these things:可能是这两件事:
Code:代码:
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])
Might want, depending on your server response time, add a failsafe for pending queries (example, if you sent out a query and the next one launches before the first one returns...).可能需要,根据您的服务器响应时间,为挂起的查询添加故障保护(例如,如果您发出查询并且下一个在第一个返回之前启动......)。
For React Hooks + Apollo to fetch data from a GraphQL server every 5 seconds. React Hooks + Apollo 每 5 秒从 GraphQL 服务器获取数据。 In this example, we logout the user in React if the user is not logged-in in the backend.
在这个例子中,如果用户没有在后端登录,我们在 React 中注销用户。 (JWT token not valide anymore)
(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
`const [time, setTime] = useState(0)
useEffect(()=>{
setInterval(()=>{
setTime(prev => prev + 1)
}, 1000)
},[])`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.