我同时开始使用React和TypeScript,在我的应用程序中实现一些基本身份验证时遇到了一个问题。我一直以Ryan Chenkie的Orbit App及其关于React安全的课程为例。
现在,我陷入了编译器,抱怨SignIn.tsx中的TS2722错误(无法调用可能未定义的对象)。我的怀疑是,我要做的就是在所有数据结构和函数调用上设置适当的类型,但是如何以及在哪里设置它们,在某种程度上暗示了我。所以,这是代码:
App.tsx:
这里没什么,只是一个包装在上下文提供程序中的应用程序。
import { AuthContext, authData } from "./AuthContext"
const defAuth:authData = {
userId: 0,
name: '',
token: '',
expiresAt: ''
}
const App = () => {
return (
<AuthContext.Provider value={{ authData:defAuth }}>
<Main />
</AuthContext.Provider>
);
}
AuthContext.tsx:
调用我尝试使用各种默认参数的createContext()时,通常的想法是可以调用authContext.setState()并将数据传递给它。我使用的是Partial前缀,因此不必将setState()传递给Provider元素。
export interface authData {
userId: number
name: string
token: string
expiresAt: string
}
interface IAuthContext {
authData: authData,
setState: (authInfo:authData) => void
}
const AuthContext = createContext<Partial<IAuthContext>>(undefined!)
const { Provider } = AuthContext
const AuthProvider: React.FC<{}> = (props) => {
const [authState, setAuthState] = useState<authData>()
const setAuthInfo = (data:authData) => {
console.log('Called setAuthInfo')
setAuthState({
userId: data!.userId,
name: data!.name,
token: data!.token,
expiresAt: data!.expiresAt
})
}
return (
<Provider
value={{
authData: authState,
setState: (authInfo:authData) => setAuthInfo(authInfo)
}} {...props}
/>
)
}
export { AuthContext, AuthProvider }
SignIn.tsx:
这又是一个基本的登录组件,带有表单和onSubmit处理函数。一切正常,直到我向其添加authContext为止。我只包含了相关代码。
interface loginType extends Record<string, any>{
email: string,
password: string,
remember: boolean
}
const SignIn = () => {
const authContext = useContext(AuthContext)
const { register, handleSubmit, errors } = useForm<loginType>()
const onSubmit = async (data:loginType) => {
const ret = await apiFetch.post('process_login/', formData )
console.log(ret.data)
console.log('Printing context')
authContext.setState(ret.data)
console.log(authContext)
}
/* ... ... */
}
如前所述,编译器在SignIn.tsx
的{{1}}抱怨说它可能是未定义的。我尝试使用各种参数调用authContext.setState(ret.data)
,试图传递一些默认值,这些默认值将告诉编译器稍后在运行时定义createContext()
的位置。我尝试以几种不同的方式调用setState,但没有任何效果。
这显然可以在普通JSX中使用,我真的很想找到一种使其在TSX中可以使用的方法。
答案 0 :(得分:0)
这是您需要做的:
首先在App.tsx
中,您必须使用AuthProvider
而不是AuthContext.Provider
。这样,您就可以摆脱value属性。
<AuthProvider>
<Main />
</AuthProvider>
然后,在AuthContext.tsx
中,创建上下文时无需使用Partial前缀。因此,对IAuthContext
进行一些调整,然后在创建上下文时传递一些默认数据。
interface IAuthContext {
authData: authData | undefined,
setState: (authInfo:authData) => void
}
const AuthContext = createContext<IAuthContext>( {
authData: defaultAuthData,
setState: () => {}
})
现在您可以调用authContext.setState()
,将数据作为authData
类型进行传递。