I have a React hook I'm using to set the values on a Context provider.
const useAuth = () => {
const [token, setToken] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [tryAuth, setTryAuth] = useState(false);
useEffect(() => {
if (tryAuth) {
const getToken = async () => {
console.log("triggered");
setIsLoading(true);
const axiosInstance = axios.get<TokenResponseType>(
"http://localhost:3500/token"
);
const tokenResult = (await axiosInstance).data.accessToken;
setToken(tokenResult);
setIsLoading(false);
};
getToken();
}
}, [tryAuth]);
return [{ token, isLoading }, setTryAuth];
};
export default useAuth;
export type inferredType = ReturnType<typeof useAuth>;
VSCode tells me the return type is as follows:
(alias) useAuth(): (React.Dispatch<React.SetStateAction<boolean>> | {
token: string;
isLoading: boolean;
})[]
Because I couldn't figure out how to describe the type I used the following approach:
export type inferredReturnType = ReturnType<typeof useAuth>;
And I'm initializing my React Context with the following line:
const AuthContext = React.createContext<inferredReturnType | undefined>(undefined);
However when I'm trying to use the hook in a Component as follows:
const [{ token, isLoading }, setTryAuth] = useAuth();
I'm getting the error message
Property 'token' does not exist on type 'Dispatch<SetStateAction> | { token: string; isLoading: boolean; }'.ts(2339).
Only suppressing the TSCompiler with //@ts-ignore made it work so far.
Here the code for the Context and context provider:
const AuthContext = React.createContext<inferredReturnType | undefined>(undefined);
const AuthContextProvider = (props: any) => {
//@ts-ignore
const [{ token, isLoading }, setTryAuth] = useAuth();
return (
<AuthContext.Provider value={[{ token, isLoading }, setTryAuth]}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContextProvider;
export const useAuthContext = () => {
//@ts-ignore
const [{ token, isLoading }, setTryAuth] = useContext(AuthContext);
if (token === undefined)
throw new Error('useAuthContext must be inside a Provider with a value');
return [{ token, isLoading }, setTryAuth];
};
Here is the link to the Code Sandbox:
What I'm trying to achieve is described under "Custom Data fetching hook" in the excellent blog post by Robin Wieruch just for TypeScript.
I'm sure it's some advanced type destructuring thingy from ES6 in combination with TypeScript that's messing with my head but I can't find a good article / docu to read up on it.
Thanks for your help!
