我使用 firebase 身份验证进行用户身份验证,并使用 react-navigation 根据用户状态呈现不同的导航器。在 Firebase.js 中,我监听 auth 状态变化并相应地设置状态。问题是,当我设置用户数据并隐藏启动画面(npm package react-native-splash-screen)时,在呈现主堆栈之前仍然可以看到身份验证堆栈。我想问一个问题,这个怎么解决?
Firebase.js 上下文提供程序
class Firebase extends React.Component {
constructor(props: Props) {
super(props);
this.state = {
user: null,
userDoc: null,
isLoading: true,
};
}
usersRef = firestore().collection('Users');
componentDidMount() {
const { isLoading, user } = this.state;
auth().onAuthStateChanged(res => {
if (res) {
this.usersRef?.doc(res.uid).onSnapshot(async snapshot => {
this.setState(
{
user: res,
userDoc: snapshot.exists ? snapshot.data() : null,
isLoading:false
},
() => SplashScreen.hide();
);
});
} else {
this.setState(
{
user: null,
isUserSubscribed: false,
isLoading: false,
},
() => SplashScreen.hide();
);
}
});
}
}
RootNavigator.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MainNavigatorWrapper from '../MainNavigator';
import AuthNavigator from '../AuthNavigator';
import { useFirebase } from '../../context';
const Stack = createNativeStackNavigator();
const RootNavigator = () => {
const { user } = useFirebase();
return (
<NavigationContainer>
<Stack.Navigator}>
{!user ? (
<Stack.Screen name="Auth" component={AuthNavigator} />
) : (
<Stack.Screen name="Main" component={MainNavigatorWrapper} />
)}
</Stack.Navigator>
</NavigationContainer>
);
};
答案 0 :(得分:1)
我发布此信息是因为我正在寻找解决同一问题的方法。我想出了一个黑客。我确信有更好的方法来解决这个问题,但我还没有弄清楚。这就是我所做的。
在 App.js 中,我返回:
export default function App() {
const [dataLoaded, setDataLoaded] = useState(false)
useEffect(() => {
async function loadApp() {
try {
await SplashScreen.preventAutoHideAsync()
// DO APP LOADING STUFF HERE
} catch (err) {
console.warn(err)
} finally {
setDataLoaded(true)
}
}
loadApp()
}, [])
if (!dataLoaded){
return null
}
return (
<AuthenticationContextProvider>
<Navigation />
</AuthenticationContextProvider>
)
}
如您所见,我使用的是 expo 的 SplashScreen
API。因此,诀窍是将所有内容隐藏在启动画面后面,直到身份验证得到解决。
我的导航组件如下所示:
export const Navigation = () => {
const { isAuthenticated } = useContext(AuthenticationContext)
const splashHiddenRef = useRef(false)
useEffect(() => {
// splash screen hasn't been hidden yet and authentication has already been determined
if (!splashHiddenRef.current && isAuthenticated !== null) {
// delay the splash screen from hiding to quick. Otherwise, the AuthenticationNavigator
// will flash before the AppNavigator is shown (when user is already authenticated on load)
setTimeout(() => {
hideAsync()
}, 1000)
}
}, [isAuthenticated])
return <NavigationContainer>{isAuthenticated ? <AppNavigator /> : <AccountNavigator />}</NavigationContainer>
}
如您所见,我将启动画面的隐藏延迟了 1 秒。如果网络连接速度较慢,这可能不起作用。我不确定。就目前而言,这是一种我正在搞砸的黑客行为。
我在这次黑客攻击之前的尝试:
它以前不起作用,但在我的上下文中 isAuthenticated
的初始值为 null。当应用加载时,一旦身份验证得到解决,该值将变为真或假(不再为空)。所以,我假设一旦 auth 不为空,那么它应该加载正确的导航器,而不会出现 auth 导航器的闪烁。我相信这与布局的初始渲染有关。 SpashScreen
API 像这样解决了这个问题:
问题是这不是一个很好的例子。据我所知,您不能在导航器中使用 onLayout
。我认为您只能在 React.View
的子类中使用它。
也许有人可以提供更好的解决方案......这对我有用......现在