Ошибка возникает в моем файле useCachedResources.ts, но я не уверен, почему. Это три файла, с которыми я работаю. Я подозреваю, что это связано с тем, что значение изначально было нулевым в первый раз, но я условно отображаю свои стеки навигации Auth и App. Кроме того, с шаблоном был предоставлен useCachedResources, поэтому, может быть, мне следует добавить в него firebase onAuthStateChanged?
Аутентикатидеусерпровидер.tsx
import { useState, createContext } from 'react';
export interface IUser {
uuid: string;
email: string | null;
}
export type AuthContextType = {
user: IUser;
setUser: (newUser: IUser | null) => void;
};
export const AuthenticatedUserContext = createContext<AuthContextType | null>(null);
export const AuthenticatedUserProvider = ({ children }: { children: React.ReactNode }) => {
const [user, setUser] = useState<IUser | null>(null);
return (
<AuthenticatedUserContext.Provider value={user ? { user, setUser } : null}>
{children}
</AuthenticatedUserContext.Provider>
);
};
навигация.ts
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
const { user } = useContext(AuthenticatedUserContext) as AuthContextType;
return (
<NavigationContainer linking={LinkingConfiguration} theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
{user ? <AppStack /> : <AuthStack />}
</NavigationContainer>
);
}
использоватьCachedResources.ts
export default function useCachedResources() {
const { user, setUser } = useContext(AuthenticatedUserContext) as AuthContextType;
const [isLoadingComplete, setLoadingComplete] = useState(false);
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHideAsync();
await Font.loadAsync({
...FontAwesome.font,
'poppins-400': require('../assets/fonts/poppins-400.ttf'),
'poppins-700': require('../assets/fonts/poppins-700.ttf'),
'poppins-900': require('../assets/fonts/poppins-900.ttf'),
});
const unsubscribeAuthStateChanged = onAuthStateChanged(auth, (authenticatedUser) => {
authenticatedUser ? setUser({ uuid: authenticatedUser.uid, email: authenticatedUser.email }) : setUser(null);
});
return unsubscribeAuthStateChanged;
} catch (e) {
console.warn(e);
} finally {
setLoadingComplete(true);
SplashScreen.hideAsync();
}
}
loadResourcesAndDataAsync();
}, [user]);
return isLoadingComplete;
}
Поскольку вы инициализируете свой контекст с помощью null
, вы не можете использовать деструктурирование. Например, это...
const { user } = null;
в браузере выдает следующую ошибку
Uncaught TypeError: Cannot destructure property 'user' of 'null' as it is null.
Мой совет состоял бы в том, чтобы инициализировать ваш контекст фиктивным значением. Это также избавит вас от необходимости использовать as AuthContextType
везде.
export type AuthContextType = {
user: IUser | null; // make user optional instead of the context
setUser: (newUser: IUser | null) => void;
};
// initialise with a dummy / no-op context
export const AuthenticatedUserContext = createContext<AuthContextType>({
user: null,
setUser: () => {}
});
export const AuthenticatedUserProvider: React.FC = ({ children }) => {
const [user, setUser] = useState<IUser | null>(null);
return (
<AuthenticatedUserContext.Provider value={{ user, setUser }}>
{children}
</AuthenticatedUserContext.Provider>
);
};