[英]The “Can't perform a React state update on an unmounted component” error
I have a problem with useEffect
, Im loading data from firebase, and it works.. BUT sometimes there is an error in console looks like this:我有
useEffect
的问题,我从 firebase 加载数据,它可以工作.. 但有时控制台中的错误如下所示:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s, a useEffect cleanup function,
in OrdersScreen (at SceneView.tsx:122)
in StaticContainer
in StaticContainer (at SceneView.tsx:115)
in EnsureSingleNavigator (at SceneView.tsx:114)
in SceneView (at useDescriptors.tsx:150)
in RCTView (at CardContainer.tsx:221)
in RCTView (at CardContainer.tsx:220)
in RCTView (at CardSheet.tsx:33)
in ForwardRef(CardSheet) (at Card.tsx:563)
in RCTView (at createAnimatedComponent.js:144)
in AnimatedComponent (at createAnimatedComponent.js:194)
in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:545)
in PanGestureHandler (at GestureHandlerNative.tsx:13)
in PanGestureHandler (at Card.tsx:539)
in RCTView (at createAnimatedComponent.js:144)
in AnimatedComponent (at createAnimatedComponent.js:194)
in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:535)
in RCTView (at Card.tsx:529)
in Card (at CardContainer.tsx:189)
in CardContainer (at CardStack.tsx:558)
in RCTView (at Screens.tsx:69)
in MaybeScreen (at CardStack.tsx:551)
in RCTView (at Screens.tsx:48)
in MaybeScreenContainer (at CardStack.tsx:461)
in CardStack (at StackView.tsx:458)
in KeyboardManager (at StackView.tsx:456)
in SafeAreaProviderCompat (at StackView.tsx:453)
in RCTView (at StackView.tsx:452)
in StackView (at createStackNavigator.tsx:85)
in StackNavigator (at ShopNavigator.js:162)
in OrdersNavigator (at SceneView.tsx:122)
in StaticContainer
in StaticContainer (at SceneView.tsx:115)
in EnsureSingleNavigator (at SceneView.tsx:114)
in SceneView (at useDescriptors.tsx:150)
in RCTView (at ResourceSavingScene.tsx:43)
in RCTView (at ResourceSavingScene.tsx:26)
in ResourceSavingScene (at DrawerView.tsx:168)
* [native code]:null in __expoConsoleLog
- node_modules\react-native\Libraries\LogBox\LogBox.js:33:4 in console.error
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:197:6 in registerError
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:84:8 in errorImpl
- node_modules\react-native\Libraries\YellowBox\YellowBox.js:63:4 in console.error
- node_modules\expo\build\environment\muteWarnings.fx.js:27:4 in error
- node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:608:6 in warningWithoutStack
- node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:21972:25 in warnAboutUpdateOnUnmountedFiberInDEV
- node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:19813:40 in scheduleUpdateOnFiber
- node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:11880:16 in dispatchAction
* [native code]:null in dispatchAction
* screens\shop\OrdersScreen.js:28:15 in useCallback$argument_0
- node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
- node_modules\regenerator-runtime\runtime.js:293:29 in invoke
- node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
- node_modules\regenerator-runtime\runtime.js:154:27 in invoke
- node_modules\regenerator-runtime\runtime.js:164:18 in PromiseImpl.resolve.then$argument_0
- node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
- node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:135:14 in _callTimer
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:183:16 in _callImmediatesPass
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:446:30 in callImmediates
* [native code]:null in callImmediates
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:396:6 in __callImmediates
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:144:6 in __guard$argument_0
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:373:10 in __guard
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:143:4 in flushedQueue
* [native code]:null in flushedQueue
* [native code]:null in invokeCallbackAndReturnFlushedQueue
and there is my code of OrdersScreen.js
:还有我的
OrdersScreen.js
代码:
import React, { useCallback, useEffect, useState } from 'react'
import { StyleSheet, View, Text, FlatList } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'
import * as ordersActions from '../../store/actions/orders'
import OrderItem from '../../components/shop/OrderItem'
import Loading from '../../components/UI/Loading'
import ErrorMessage from '../../components/UI/ErrorMessage'
const OrdersScreen = (props) => {
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState()
const orders = useSelector((state) => state.orders.orders).sort(function (a, b) {
return new Date(b.date) - new Date(a.date)
})
const dispatch = useDispatch()
const loadOrders = useCallback(async () => {
let mounted = true
setError()
setIsLoading(true)
try {
await dispatch(ordersActions.fetchOrders())
} catch (err) {
setError(err.message)
}
if (mounted) {
setIsLoading(false)
}
return function cleanup() {
mounted = false
}
}, [dispatch, setError, setIsLoading])
useEffect(() => {
loadOrders()
}, [])
if (error) {
return <ErrorMessage onReload={loadOrders} />
}
if (isLoading) {
return <Loading />
}
return (
<View>
<FlatList
data={orders}
keyExtractor={(item) => item.id}
renderItem={(itemData) => (
<OrderItem
amount={itemData.item.totalAmount}
date={itemData.item.readableDate}
items={itemData.item.items}
status={itemData.item.status}
/>
)}
ListEmptyComponent={
!isLoading && (
<Text style={{ textAlign: 'center', marginTop: 20 }}>
Ваш список заказов пока пуст.. 📄
</Text>
)
}
/>
</View>
)
}
const styles = StyleSheet.create({
screen: { flex: 1, justifyContent: 'center', alignItems: 'center' },
})
export default OrdersScreen
categories.js - action: categories.js - 动作:
import Category from '../../models/categories'
export const SET_CATEGORIES = 'SET_CATEGORIES'
export const fetchCategories = () => {
return async (dispatch, getState) => {
try {
const response = await fetch('https://shopapp-6f444.firebaseio.com/categories.json')
if (!response.ok) {
throw new Error('Something went wrong when we recieve categories')
}
const respData = await response.json()
const loadedCategories = []
for (const key in respData) {
loadedCategories.push(
new Category(key, respData[key].title, respData[key].imageUrl, respData[key].description)
)
}
dispatch({
type: SET_CATEGORIES,
categories: loadedCategories,
})
} catch (err) {
throw err
}
}
}
any help or advice please!请提供任何帮助或建议! Thank you a lot!
十分感谢!
You are changing react state in catch block, if component becomes unmounted, during error in your request, most probably, you will see that error.您正在更改 catch 块中的 react state,如果组件被卸载,在您的请求出错期间,您很可能会看到该错误。
Try changing the content of catch block to this:尝试将 catch 块的内容更改为:
if (mounted) {
setError(err.message)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.