我有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>
)
}
答案 0 :(得分:2)
您需要清除interval
,
useEffect(() => {
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 => 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])
有关cleanup
中的useEffect
函数的更多信息,请参考this。
答案 1 :(得分:2)
可能是这两个东西
代码:
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])
可能需要根据服务器响应时间,为挂起的查询添加故障保护(例如,如果您发出查询,并且下一个查询在第一个查询返回之前启动...)。
答案 2 :(得分:0)
React Hooks + Apollo 每 5 秒从 GraphQL 服务器获取数据。 在这个例子中,如果用户没有在后端登录,我们在 React 中注销用户。 (JWT 令牌不再有效)
Private Sub Workbook_Open()
Dim WB As Workbook
On Error Resume Next
Set WB = Workbooks("Test.xlsx")
If Err Then
MsgBox "Test" & vbNewLine & "" & vbNewLine & "" & "Test" & vbNewLine & "" & vbNewLine & "Test" & vbNewLine & "" & vbNewLine & "Test"
'ThisWorkbook.Close
End If
Workbooks("TestA.xlsx").Worksheets("TestA").ShowAllData
Workbooks("TestA.xlsx").Worksheets("TestA").Range("A2:AF666").Copy _
Workbooks("TestB.xlsm").Worksheets("TestB").Range("A2")
Worksheets("TestC").Range("A1").AutoFilter Field:=1, Criteria1:="JA"
Workbooks("TestB.xlsm").Worksheets("TestB").Range("B2:AF666").Copy _
Workbooks("TestB.xlsm").Worksheets("TestC").Range("B2")
On Error GoTo 0
End Sub