我正在尝试学习如何在React中使用钩子和上下文,但是需要使用TypeScript(以及它的新功能)。
我的用例是授权:用户已登录或未登录,并且具有角色(例如,“管理员”,“超级管理员”)。根据其授权状态,导航栏的呈现方式会有所不同。
除其他外,我尝试遵循此示例,以简化我的需求。
到目前为止,这是我的上下文和提供者:
import React, { createContext, useContext, Context, FC SetStateAction, useState } from 'react';
export interface IAuth {
loggedIn: boolean,
role: string
}
export const AuthContext = React.createContext<IAuth>({
loggedIn: false,
role: ''
});
const AuthProvider: FC = ({children}) => {
const [auth, setAuth] = useState({
loggedIn: false,
role: ''
});
return (
<AuthContext.Provider value={/*What to set as value?*/}>
{children}
</AuthContext.Provider>
)
}
export default AuthProvider;
然后是我的NavBar,它使用了上下文的Consumer:
class Nav extends React.Component {
render() {
return (
<AuthContext.Consumer>
{context => (
< div >
.. stuff ...
</div>
<ul className="nav">
{context.loggedIn ? (
<Fragment> .. links .. </Fragment>
) : (<Fragment> .. links .. </Fragment>
)}
</ul>
</div>
)
}
</AuthContext.Consumer>
)
}
} export default Nav;
如果我将提供者的值设置为这样,则所有这些工作正常:
<AuthContext.Provider value={{
loggedIn: false,
role: 'someRole'
}}>
但是,我也想提供该setAuth
功能,以便从Login组件等更改这些值。
使用以下命令给我错误:
<EmailContext.Provider value={[state, setState]}>
即 Type '({ loggedIn: boolean; role: string; } | Dispatch<SetStateAction<{ loggedIn: boolean; role: string; }>>)[]' is missing the following properties from type 'IAuth': loggedIn, role
使用以下内容也会给我错误:
<AuthContext.Provider value={{data: auth,
updateAuth: () => { setAuth({... auth, loggedIn: true})}
}}>
错误data: auth
:Type '{ data: { loggedIn: boolean; role: string; }; updateAuth: () => void; }' is not assignable to type 'IAuth'. Object literal may only specify known properties, and 'data' does not exist in type 'IAuth'.
我尝试过的其他其他事情也有类似的错误。
这些都是打字稿错误。如何set
以与Typescript兼容的方式设置提供程序的值-并包括操作而不只是值?
首先定义一个接口,其中包含应通过上下文传递的所有内容
export interface IAuth {
loggedIn: boolean;
role: string;
logIn: () => void;
logOut: () => void;
}
然后提供者
export const AuthContext = React.createContext<IAuth>(null);
const AuthProvider: FC = ({ children }) => {
const [auth, setAuth] = useState({
loggedIn: false,
role: ""
});
const logIn = () => {
setAuth(prevState => ({
...prevState,
loggedIn: true
}));
};
const logOut = () => {
setAuth(prevState => ({
...prevState,
loggedIn: false
}));
};
return (
<AuthContext.Provider
// Here as value you need to pass the same interface as IAuth
// You can also just pass setAuth and do whatever you want
// from the children
value={{
...auth,
logIn,
logOut
}}>
{children}
</AuthContext.Provider>
);
};
然后,在您的使用者中,您可以使用useContext
钩子来访问值
const Child: FC = () => {
const { loggedIn, role, logIn, logOut } = useContext(AuthContext);
return (
<div>
<p>{`loggedIn: ${loggedIn}`}</p>
<p>{`role: ${role}`}</p>
<button onClick={logIn}>logIn</button>
<button onClick={logOut}>logOut</button>
</div>
);
};
最后将渲染Child
为AuthProvider
const App: FC = () => (
<AuthProvider>
<Child />
</AuthProvider>
);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句