为啥在导航之前加载了我的另一个屏幕?

Posted

技术标签:

【中文标题】为啥在导航之前加载了我的另一个屏幕?【英文标题】:Why my other screen is loaded before navigate?为什么在导航之前加载了我的另一个屏幕? 【发布时间】:2021-12-11 13:13:26 【问题描述】:

我只使用导航 5。我有启动画面、登录和主选项卡屏幕。我的堆栈已经从启动 --> 登录 --> 主选项卡排序。最终,登录屏幕在启动时首先加载,但屏幕显示启动画面部分。在登录加载时,我会检查与域的连接,并且问题出来告诉Warning: Can't perform a React state update on an unmounted component

导航容器.js

const LoginStack = createNativeStackNavigator();
function NavigatorLogin() 
    return (
        <LoginStack.Navigator>
            <LoginStack.Screen name="AppSignIn" component=AppSignIn />
            * .... etc *
        </LoginStack.Navigator>
    );


const MainTabStack = createNativeStackNavigator();
function NavigatorMainTab() 
    return (
        <MainTabStack.Navigator>
            * .... etc *
        </SupervisorStack.Navigator>
    );


const StackApp = createNativeStackNavigator();
export const AppStackNavigator = () => 
    const [appState, setAppState] = React.useState();
    const [dataState, setDataState] = React.useState();
    const [initialRoute, setInitialRoute] = React.useState('NavigatorLogin');
    const state =  appState, setAppState ;
    const datas =  dataState, setDataState ;
    React.useEffect(() => 
        setAppState( IsLoading: true, IsLoggedIn: false );
        setDataState( taskitem:  );
        console.log('App state 1: ', appState);
    , []);
    React.useEffect(() => 
        console.log('App state: ', appState);
    , [appState]);
    return (
        <AppContext.Provider value=state>
            appState.IsLoading ? (
                <AppSplash />
            )
                : (
                    <NavigationContainer>
                        <StackApp.Navigator initialRouteName=initialRoute>
                            
                                appState.IsLoggedIn
                                    ?
                                    <StackApp.Screen name='NavigatorMainTab' component=NavigatorMainTab/>
                                    :
                                    <StackApp.Screen name='NavigatorLogin' component=NavigatorLogin/>
                            
                        </StackApp.Navigator>
                    </NavigationContainer>
                )
        </AppContext.Provider>
    )

AppSignIn.js

export const AppSignIn = () => 
    const isMountedRef = React.useRef(false);
    const  appState, setAppState  = React.useContext(AppContext);

    React.useState(() => 
        console.log('Hello from sign in screen; ', appState)
        isMountedRef.current = true;
        if (isMountedRef.current) 
            // check domain connection
        
        return () => 
            unsubscribe();
            isMountedRef.current = false;
        
    , []);
    return (
        <SafeAreaView style= flex: 1 >
        </SafeAreaView>
    )

在终端显示如下:

     LOG  Running "myproject" with "rootTag":41
     LOG  Hello from sign in screen;  
     LOG  App state 1:  
     LOG  App state:  
     ERROR  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 a useEffect cleanup function.
        in AppSignIn (at SceneView.tsx:126)
        in StaticContainer
        in EnsureSingleNavigator (at SceneView.tsx:118)
        in SceneView (at useDescriptors.tsx:209)
        in RCTView (at View.js:32)
        in View (at DebugContainer.native.tsx:27)
        in DebugContainer (at NativeStackView.native.tsx:71)
        in MaybeNestedStack (at NativeStackView.native.tsx:229)
        in RNSScreen (at createAnimatedComponent.js:243)
        in AnimatedComponent (at createAnimatedComponent.js:296)
        in AnimatedComponentWrapper (at src/index.native.tsx:169)
        in Screen (at NativeStackView.native.tsx:175)
        in SceneView (at NativeStackView.native.tsx:277)
        in RNSScreenStack (at NativeStackView.native.tsx:268)
        in NativeStackViewInner (at NativeStackView.native.tsx:322)
        in RCTView (at View.js:32)
        in View (at SafeAreaProviderCompat.tsx:42)
        in SafeAreaProviderCompat (at NativeStackView.native.tsx:321)
        in NativeStackView (at createNativeStackNavigator.tsx:67)
        in NativeStackNavigator (at navigation-container.js:20)
        in NavigatorLogin (at SceneView.tsx:126)
        in StaticContainer
        in EnsureSingleNavigator (at SceneView.tsx:118)
        in SceneView (at useDescriptors.tsx:209)
        in RCTView (at View.js:32)
        in View (at DebugContainer.native.tsx:27)
        in DebugContainer (at NativeStackView.native.tsx:71)
        in MaybeNestedStack (at NativeStackView.native.tsx:229)
        in RNSScreen (at createAnimatedComponent.js:243)
        in AnimatedComponent (at createAnimatedComponent.js:296)
        in AnimatedComponentWrapper (at src/index.native.tsx:169)
        in Screen (at NativeStackView.native.tsx:175)
        in SceneView (at NativeStackView.native.tsx:277)
        in RNSScreenStack (at NativeStackView.native.tsx:268)
        in NativeStackViewInner (at NativeStackView.native.tsx:322)
        in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
        in SafeAreaProvider (at SafeAreaProviderCompat.tsx:46)
        in SafeAreaProviderCompat (at NativeStackView.native.tsx:321)
        in NativeStackView (at createNativeStackNavigator.tsx:67)
        in NativeStackNavigator (at navigation-container.js:72)
        in EnsureSingleNavigator (at BaseNavigationContainer.tsx:430)
        in BaseNavigationContainer (at NavigationContainer.tsx:132)
        in ThemeProvider (at NavigationContainer.tsx:131)
        in NavigationContainerInner (at navigation-container.js:71)
     LOG  App state:  "IsLoading": true, "IsLoggedIn": false, "IsSupervisor": false
     LOG  splash info here
     LOG  Hello from sign in screen;  "IsLoading": false
     LOG  App state:  "IsLoading": false

最初我没有使用 useRef。我使用它作为发现类似的问题,但它仍然错误。我也使用如下功能,但仍然有错误。我不确定其他选项或如何判断我的问题的正确词是什么。

function useIsMountedRef() 
    const isMountedRef = React.useRef(null);
    React.useEffect(() => 
        isMountedRef.current = true;
        return () => isMountedRef.current = false;
    , []);
    return React.useCallback(() => isMountedRef.current, []);


.
.
.
const isMountedRef = useIsMountedRef();

【问题讨论】:

【参考方案1】:

经过几天的搜索和尝试错误,终于警告消失了。

由于我使用上下文 API 来替换 switch navigator,因此我在挂载时使用上下文而不是 isMountedRef 进行检查。

删除旧代码

编辑:通过在屏幕安装上进行变量检查,这是绝对不合适的,因为当与服务器的连接失败时计时器将不会运行。解决方案在于navigation-container.js

/// This is original from first post
const [appState, setAppState] = React.useState();

/// I change to this
const [appState, setAppState] = React.useState( IsLoading: true, IsLoggedIn: false );

我的 AppSignIn.js

React.useEffect(() => 
    console.log('Login screen mounted');
    const unsubscribe = NetInfo.addEventListener(async state => 
        setIsPhoneConnected(state.isConnected);
        console.log('Phone connected? ' + state.isConnected + ', Server connected? ' + IsServerConnected)
    );
    
  CheckServerConnection()
       .then((response) => 
           console.log(response);
           setIsServerConnected(true);
       )
       .catch((error) => 
           setIsServerConnected(false);
           ResetTimer(5);
       );
    return () => 
        unsubscribe();
    
, []);

【讨论】:

以上是关于为啥在导航之前加载了我的另一个屏幕?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的导航栏在 Xcode 中消失了?

从嵌套屏幕导航到不同选项卡堆栈中的另一个嵌套屏幕(反应导航)

为啥 PHP 会弄乱我的 CSS?

我已经加载了一个 1.5GB 的 csv 文件并成功加载了我的表大小是 250MB 为啥会这样?

为啥我的 UITabBar 在载入屏幕加载后消失?

React Navigation 5 - 在导航到它之前从另一个选项卡中的另一个堆栈重置堆栈(类似于 popToTop())