我在简单的打字稿应用程序中使用Auth上下文。
我的上下文声明在文件中
AuthProvider.tsx
,如下所示:
import React, { createContext, useState } from 'react';
import auth from '@react-native-firebase/auth';
export interface IAuth {
user,
setUser,
login,
register,
logout
}
export const AuthContext = createContext<IAuth | null>(null);
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AuthContext.Provider
value={{
user: user,
setUser: setUser,
login: async (email, password) => {
try {
await auth().signInWithEmailAndPassword(email, password);
} catch (e) {
console.log(e);
}
},
register: async (email, password) => {
try {
await auth().createUserWithEmailAndPassword(email, password);
} catch (e) {
console.log(e);
}
},
logout: async () => {
try {
await auth().signOut();
} catch (e) {
console.log(e);
}
},
}}>
{children}
</AuthContext.Provider>
);
};
这就是我在其他地方使用它的方式:
const { user, setUser } = useContext(AuthContext);
但是Typescript在此留置权上抛出2个错误:
我该怎么做才能绕过它?
答案 0 :(得分:1)
创建上下文时,您需要提供一个默认值,但是您使用空值创建它。
在您的情况下,您可能正在使用useContextHook从另一个组件访问它
请考虑这种情况,如果您直接访问它而不提供提供者级别的值,并且从上下文访问用户或其他字段,它将不会在那里。因此它抱怨说这些值不存在,要解决此问题,您必须提供如下所示的默认值(您也应在IAuth中设置其他字段)。
export const AuthContext = createContext<IAuth | null>({user:{},setUser:()=>{}});
答案 1 :(得分:0)
我想您可以将其转换为IAuth
const { user, setUser } = useContext(AuthContext) as IAuth
答案 2 :(得分:0)
推断是正确的,上下文可能为null。进行空检查:
const ctx = useContext(AuthContext);
if(ctx !== null) {
const { user, setUser } = ctx;
// ...
}
答案 3 :(得分:0)
在这里,您已经说过AuthContext
的内容可以是IAuth
对象,也可以是null
。
export const AuthContext = createContext<IAuth | null>(null);
不能将useContext(AuthContext)
的值看成一个对象,因为您尚未验证它实际上是IAuth
而不是null
。
有很多解决方法。
一种方法是您仍然可以将上下文值设置为null
,但是我们必须在使用它之前进行检查。这有效并且易于实现。如果值不存在,我们可以通过返回null来提前退出组件。但是,您必须确保仅在调用所有其他钩子之后退出,否则将收到“违反了钩子规则”错误。
export const Consumer = () => {
const context = useContext(AuthContext);
if ( ! context ) {
return null;
}
const { user, setUser } = context;
return (
<div/>
)
}
另一种方法是我们允许一个空的或不完整的对象,而不是null
。这使我们能够进行结构调整,但是我们只是将错误向下移动,因为我们对user
和setUser
进行结构调整的两个值可能具有预期值,或者可能是undefined
。>
export const AuthContext = createContext<Partial<IAuth>>({});
const { user, setUser } = useContext(AuthContext);
更详细的方法是使用伪方法为满足IAuth
接口的上下文创建默认值。这些函数应该是可调用的,这样就不会产生错误,但是它们什么也不做。
const defaultValue: IAuth = {
setUser: () => console.error("attempting to use AuthContext outside of a valid provider"),
/*... */
}
export const AuthContext = createContext<IAuth>(defaultValue);
您的界面确实看起来像您发布的内容,还是只是出于问题的考虑而删除了这些值?接口需要定义与每个键关联的类型,而不仅仅是列出键。