Issue
so in my React App i use Private Routes in my routing component:
const PrivateRoute = ({ children }: { children: ReactNode }) => {
const { session } = useAuth();
return !session ? <Navigate to={"/"} /> : children;
};
UseAuth hook:
export const useAuth = () => {
const session = useContext(AuthContext);
if (!session) {
return { session: null, currentUser: null };
}
const currentUser = session.user;
return { session, currentUser };
};
Here is example of Dashboard component nested in Private Route:
<Route
path="/dashboard"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
/>
Now in my Dashboard Component im getting error 'currentUser' is possibly 'null'
:
const { currentUser } = useAuth();
const { data: user_assignments } = useGetUserAssignments(currentUser.id);
Why in my private routes components i'm receiving that 'currentUser' is possibly 'null'.ts(18047)
when it clearly only renders components when session is not null?
Solution
The Dashboard
component isn't aware that it is being conditionally rendered. Typescript can only infer the provided Context value/type returned from the useAuth
hook, which includes currentUser
being null.
You can use the Optional Chaining Operator (?.
) or a null-check/guard-clause to check if currentUser
exists, and provide a valid fallback value to the useGetUserAssignments
hook.
const { currentUser } = useAuth();
const { data: user_assignments } = useGetUserAssignments(currentUser?.id ?? "");
const { currentUser } = useAuth();
const { data: user_assignments } = useGetUserAssignments(
(currentUser && currentUser.id) ?? ""
);
Or if you feel reasonably confident that it's the case that currentUser
can never be null when Dashboard
is rendered you can assert this with the Non-null Assertion Operator (!
).
const { currentUser } = useAuth();
const { data: user_assignments } = useGetUserAssignments(currentUser!.id);
Just FYI
A more conventional PrivateRoute
implementation renders an Outlet
instead of a children
prop. This allows wrapping and protecting more than one route/component at-a-time.
import { Navigate, Outlet } from 'react-router-dom';
const PrivateRoute = () => {
const { session } = useAuth();
return session ? <Outlet /> : <Navigate to="/" replace />;
};
<Route element={<PrivateRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
{/* other protected routes */}
</Route>
Answered By - Drew Reese
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.