React Navigation 5 登录页先于启动页加载且报未挂载组件更新警告
问题根因
- 根路由初始状态错误,导致首次渲染先加载登录页
初始appState被设为空对象,appState.IsLoading初始值为undefined(等价于false),所以首次渲染会直接走NavigationContainer分支加载登录栈。根组件挂载后执行useEffect把IsLoading设为true,这时候会销毁已经加载的导航容器和登录页,切换显示启动页,就出现了登录页先被加载、随即被卸载,但界面显示启动页的现象。 - 登录页代码写法错误,副作用逻辑放在了
useState中
你把登录页的挂载逻辑写在了React.useState()的初始化回调里,useState的初始化函数只会在组件初始化阶段同步执行一次,你写的return清理函数完全不会被调用,isMountedRef的状态更新、异步任务中断逻辑都不会生效。当登录页被卸载后,域名检查的异步任务还在运行,结束后尝试更新状态就触发了未挂载组件更新的警告。你之前尝试的useIsMountedRef钩子本身逻辑是正确的,但因为你没有把业务逻辑放在useEffect中,钩子的挂载状态更新逻辑和业务逻辑执行时机没有对齐,所以没有生效。
修复方案
第一步:修正根路由初始状态
给appState设置正确的初始值,首次渲染直接显示启动页,避免多余的登录页加载/卸载流程:
// navigation-container.js 修改 export const AppStackNavigator = () => { // 直接设置初始状态为加载中,删掉原来设置初始appState的冗余useEffect const [appState, setAppState] = React.useState({ IsLoading: true, IsLoggedIn: false }); const [dataState, setDataState] = React.useState({ taskitem: {} }); const state = { appState, setAppState }; const datas = { dataState, setDataState }; // 仅保留监听appState变化的useEffect即可 React.useEffect(() => { console.log('App state: ', appState); }, [appState]); // 剩余渲染逻辑保持不变 }
第二步:修正登录页的副作用写法
把原来写在useState里的逻辑迁移到useEffect中,确保清理函数正常执行,同时所有异步状态更新前都判断组件挂载状态,且主动中断未完成的异步任务:
// AppSignIn.js 修改 export const AppSignIn = () => { const isMountedRef = React.useRef(false); const { appState, setAppState } = React.useContext(AppContext); // 这里原来写的是useState,改成useEffect React.useEffect(() => { console.log('Hello from sign in screen; ', appState) isMountedRef.current = true; // 示例:用AbortController中断fetch请求,可根据自己的异步逻辑替换中断方式 const abortController = new AbortController(); // 域名检查逻辑 fetch('你的域名检查地址', { signal: abortController.signal }) .then(res => res.json()) .then(res => { // 所有更新状态的操作前先判断是否挂载 if (isMountedRef.current) { // 执行你的状态更新逻辑 } }) return () => { // 中断未完成的异步任务 abortController.abort(); isMountedRef.current = false; } }, []); return ( <SafeAreaView style={{ flex: 1 }}> </SafeAreaView> ) }
可选优化
你当前是条件渲染两个路由,initialRoute配置没有实际作用,可以删除相关冗余代码。
内容的提问来源于stack exchange,提问作者Luiey
相关产品推荐
相关产品推荐

