I am planning to check my session validity on the client side every time when a page changes by using useEffect. I want to know if this is possible or what would be the possible drawbacks when I implement it that way.
This is how its gonna look like.
export default function App({ Component, pageProps }) {
useEffect(() => {
//check API to validate session
}, [Component]);
return (
<Component {...pageProps}/>
);
}
Yes man, this is possible but using NextJs you'll lose the server side rendering feature, in this case I recommend you to do something like Override the getServerSideProps function and add the session validation into it since nextJs Server side have access to cookies and session.
This is an example of what you could do:
withSSRAuth.ts (file)
import { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import {
getSession,
} from 'next-auth/client';
import { destroyCookie, parseCookies } from 'nookies';
import { AuthTokenError } from 'services/errors/AuthTokenError';
export function withSSRAuth<P>(fn: GetServerSideProps<P>): GetServerSideProps {
return async (ctx: GetServerSidePropsContext): Promise<GetServerSidePropsResult<P>> => {
const session = await getSession(ctx);
const cookies = parseCookies(ctx);
const { 'uberPlantao.user': savedUser } = cookies;
if (!session && !savedUser) {
return {
redirect: {
destination: '/',
permanent: false,
},
};
}
try {
return await fn(ctx);
} catch (err) {
if (err instanceof AuthTokenError) {
destroyCookie(ctx, 'uberPlantao.user');
destroyCookie(ctx, 'uberPlantao.token');
destroyCookie(ctx, 'uberPlantao.refreshToken');
return {
redirect: {
destination: '/',
permanent: false,
},
};
}
return err;
}
};
}
Then use it as your getServerSideProps (when you want to validate the session into some page)
page index.tsx (session validation is required)
import Image from 'next/image';
import { useRef, useCallback } from 'react';
import { FiUser, FiLock } from 'react-icons/fi';
import { useRouter } from 'next/router';
import { Form } from '@unform/web';
import { FormHandles } from '@unform/core';
import { toast } from 'react-toastify';
import * as Yup from 'yup';
import getValidationErrors from 'utils/getValidationErrors';
import { withSSRAuth } from 'utils/withSSRAuth';
import { Button } from 'components/Atoms/Button';
import { FbButton } from 'components/Atoms/FbButton';
import { Input } from 'components/Atoms/Input';
import { Seo } from 'components/Atoms/Seo';
import { Separator } from 'components/Atoms/Separator';
import {
Container, LogoContainer, FormContainer, ButtonsContainer, Footer,
} from 'styles/pages/index';
import { useAuth } from 'hooks/auth';
type DataFormInfo = {
email: string;
password: string;
}
const Home = (): JSX.Element => {
const formRef = useRef<FormHandles>(null);
const { push } = useRouter();
const { signInWithFacebook, isLoading, defaultSignIn } = useAuth();
const handleFbLogin = async (): Promise<void> => {
signInWithFacebook();
};
const handleLogin = useCallback(
async (data: DataFormInfo) => {
console.log('login');
},
[defaultSignIn, push],
);
return (
<Container>
<Seo title="Home | Uber de plantões" metaDesc="Created by thl dev" />
<LogoContainer>
</LogoContainer>
<FormContainer>
<Form ref={formRef} onSubmit={handleLogin} autoComplete="off">
</Form>
</FormContainer>
<Separator className="sep" type="horizontal" customWidth={40} />
<Footer>
</Footer>
</Container>
);
};
export default Home;
export const getServerSideProps = withSSRAuth(async () => ({
props: {},
}));
Every time that you use withSSRAuth as a wrapper of your getServerSideProps it'll validate if there's some user into cookies (you can use session too but in my case I've used cookies)
If there's no user it'll redirect to some url that you can chose into destination.
This way to validate a session isn't the best one but it prevents your page from flickering while checking if there's some user via client side