Issue
Trying to use TypeScript with React's useContext. Thought I had it figured out but get an error stating that the props do not exist when I destructure the custom hook.
Here's my custom hook - no TypeScript errors from what I see
type AppContext = {
handleLogin: HandleLogin;
};
type HandleLogin = (email: string, password: string) => void;
const AuthContext = createContext<AppContext | null>(null);
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [user, setUser] = useState(null);
const router = useRouter();
// Handle login
const handleLogin: HandleLogin = async (email: string, password: string) => {
const userData = await login(email, password);
setUser(userData);
};
return (
<AuthContext.Provider value={{ handleLogin }}>
{children}
</AuthContext.Provider>
);
};
But when I destructure the hook like so...
const { handleLogin } = useAuth();
I get the following error - * Property 'handleLogin' does not exist on type 'AppContext | null'.*
I get the same error if I include another value or function within the context's value but run into the same error. Really not sure what I'm missing.
Solution
You're assigning the initial value of context as null
, so you need to make sure the context is not null when you're restructuring. Or you can tell typescript that context will always be AppContext
.
const AuthContext = createContext<AppContext>({} as AppContext);
It's type-safe because the value will be set on the Provider when your component uses the context.
UPDATE: The below is probably a better solution.
const AuthContext = createContext<AppContext|undefined>(undefined);
export default function useAuthContext() {
const context = useContext(AuthContext);
if (!context) throw Error("useAuthContext can only be used inside an AuthProvider");
return context;
}
This gives you the type safety without any conversions. Plus a runtime check that the hook is used properly. Note that it depends on the initial value of the context being undefined.
Answered By - nullptr
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.