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.