简体   繁体   中英

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:

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 :

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:

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.

Try changing the content of catch block to this:

 if (mounted) {
     setError(err.message)
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM