为啥在导航之前加载了我的另一个屏幕?
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();
, []);
【讨论】:
以上是关于为啥在导航之前加载了我的另一个屏幕?的主要内容,如果未能解决你的问题,请参考以下文章
从嵌套屏幕导航到不同选项卡堆栈中的另一个嵌套屏幕(反应导航)
我已经加载了一个 1.5GB 的 csv 文件并成功加载了我的表大小是 250MB 为啥会这样?
React Navigation 5 - 在导航到它之前从另一个选项卡中的另一个堆栈重置堆栈(类似于 popToTop())