React Native && Firebase && useContext - "TypeError: null is not an object (evaluating '_ref.user')" with onAuthStateChanged error
React Native && Firebase && useContext - "TypeError: null is not an object (evaluating '_ref.user')" with onAuthStateChanged error
错误发生在我的 useCachedResources.ts 文件中,但我不确定原因。这是我正在处理的三个文件。我怀疑这与第一次最初为 null 的值有关,但我有条件地呈现我的 Auth 和 App 导航堆栈。另外,模板提供了 useCachedResources,所以也许我应该在其中添加 firebase onAuthStateChanged?
AuthenticatedUserProvider.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>
);
};
navigation.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>
);
}
useCachedResources.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>
);
};
错误发生在我的 useCachedResources.ts 文件中,但我不确定原因。这是我正在处理的三个文件。我怀疑这与第一次最初为 null 的值有关,但我有条件地呈现我的 Auth 和 App 导航堆栈。另外,模板提供了 useCachedResources,所以也许我应该在其中添加 firebase onAuthStateChanged?
AuthenticatedUserProvider.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>
);
};
navigation.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>
);
}
useCachedResources.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>
);
};