React Native Android应用启动页无法即时加载,切换用户时闪现旧界面问题
问题原因
你遇到的闪旧页面问题核心是onAuthStateChanged中多余的2秒定时器打乱了loading状态的控制逻辑:当你切换账号登录时,定时器会在2秒后强制将isLoading设为false,此时如果用户类型接口还没返回结果,就会用上一次缓存的userType值渲染对应页面,等接口返回后才会更新,就出现了旧页面一闪而过的问题。
除此之外你的代码还有几个逻辑漏洞需要修复:
- 监听auth状态的useEffect没有加空依赖数组,会重复订阅auth事件,导致逻辑多次触发
- 监听User变化的useEffect的清理函数位置错误,永远不会执行,可能引发组件卸载后的setState警告
- 未登录状态(User为null)下不需要请求用户类型接口,属于无效请求
修复后的代码
const App = () => { const [isLoading, setIsLoading] = useState(true); const [userType, setUserType] = useState(null); const [User, setUser] = useState(null); const getUserType = async () => { // 此处补充你自己的数据库查询逻辑获取fetchedUserType const fetchedUserType = await 实际查询用户类型的方法; setUserType(fetchedUserType); }; const onAuthStateChanged = user => { setUser(user); // 去掉多余的定时器,loading状态由用户信息查询逻辑自主控制 }; // 加空依赖数组,只订阅一次auth事件,避免重复触发 useEffect(() => { const subscriber = auth().onAuthStateChanged(onAuthStateChanged); return subscriber; }, []); useEffect(() => { let Mounted = true; // 先清空上一次的用户类型和loading状态 setUserType(null); setIsLoading(true); // 仅已登录状态下需要查询用户类型 if (User !== null) { getUserType().then(() => { if (Mounted) { setIsLoading(false); } }); } else { // 未登录状态直接结束loading,跳转登录页 setIsLoading(false); } // 清理函数放在useEffect直接返回,不要写在then回调中才能正常执行 return function cleanup() { Mounted = false; }; }, [User]); if (isLoading) { return <Splash></Splash>; } else if (User === null) { return <Login></Login>; } else if (userType === 'Admin') { return <AdminDrawerNavigator></AdminDrawerNavigator>; } else if (userType === 'Mod') { return <ModDrawerNavigator></ModDrawerNavigator>; } else { return <Fatal></Fatal>; } };
额外优化建议
如果需要保证启动页至少展示固定时长避免闪屏,可以在getUserType的查询逻辑里单独加延迟控制,不要在全局的auth监听里加定时器干扰全局状态判断。
内容的提问来源于stack exchange,提问作者Abdul Wasay
相关产品推荐
相关产品推荐

