简体   繁体   English

“无法在未安装的组件上执行 React state 更新”错误

[英]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.

相关问题 React Can't perform a React state update on an unmounted component error - React Can't perform a React state update on an unmounted component error 修复“无法对卸载的组件执行 React 状态更新”错误 - Fix "Can't perform a React state update on an unmounted component" error React - 无法在未安装的组件上执行 React state 更新 - React - Can't perform a React state update on an unmounted component React Native:无法对未安装的组件执行 React state 更新 - React Native: Can't perform a React state update on an unmounted component React:无法在未安装的组件上执行 React state 更新 - React: Can't perform a React state update on an unmounted component 导航问题 - 无法对卸载的组件执行 React 状态更新 - Navigation issue - can't perform a React state update on unmounted component 如何解决“无法对未安装的组件执行反应状态更新” - How to solve "can't perform a react state update on an unmounted component" 无法在未安装的组件主题提供程序上执行 React state 更新 - Can't perform a React state update on an unmounted component theme provider 无法使用 useEffect 挂钩对未安装的组件执行 React state 更新 - Can't perform a React state update on an unmounted component with useEffect hook 如何修复无法在未安装的组件上执行 React state 更新 - How to fix Can't perform a React state update on an unmounted component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM