在我的 NextJS 应用程序的 _app.js 中使用我的 App 函数中的 'useEffect'
Using 'useEffect' inside my App function in my _app.js for my NextJS app
我计划在每次使用 useEffect 更改页面时在客户端检查我的会话有效性。我想知道这是否可行,或者当我以这种方式实施时可能会有什么缺点。
这就是它的样子。
export default function App({ Component, pageProps }) {
useEffect(() => {
//check API to validate session
}, [Component]);
return (
<Component {...pageProps}/>
);
}
是的,这是可能的,但使用 NextJs 你会失去服务器端渲染功能,在这种情况下,我建议你做一些事情,比如覆盖 getServerSideProps 函数并在其中添加会话验证,因为 nextJs 服务器端有访问 cookie 和会话。
这是您可以执行的操作的示例:
withSSRAuth.ts(文件)
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;
}
};
}
然后将其用作您的 getServerSideProps(当您想要验证某个页面中的会话时)
第 index.tsx 页(需要会话验证)
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: {},
}));
每次你使用 withSSRAuth 作为你的 getServerSideProps 的包装器时,它都会验证是否有一些用户进入 cookies(你也可以使用会话,但在我的例子中我使用了 cookies)
如果没有用户,它将重定向到您可以选择的某些 url 目的地。
这种验证会话的方法不是最好的方法,但它可以防止您的页面在通过客户端检查是否有用户时出现闪烁
我计划在每次使用 useEffect 更改页面时在客户端检查我的会话有效性。我想知道这是否可行,或者当我以这种方式实施时可能会有什么缺点。
这就是它的样子。
export default function App({ Component, pageProps }) {
useEffect(() => {
//check API to validate session
}, [Component]);
return (
<Component {...pageProps}/>
);
}
是的,这是可能的,但使用 NextJs 你会失去服务器端渲染功能,在这种情况下,我建议你做一些事情,比如覆盖 getServerSideProps 函数并在其中添加会话验证,因为 nextJs 服务器端有访问 cookie 和会话。
这是您可以执行的操作的示例:
withSSRAuth.ts(文件)
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;
}
};
}
然后将其用作您的 getServerSideProps(当您想要验证某个页面中的会话时)
第 index.tsx 页(需要会话验证)
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: {},
}));
每次你使用 withSSRAuth 作为你的 getServerSideProps 的包装器时,它都会验证是否有一些用户进入 cookies(你也可以使用会话,但在我的例子中我使用了 cookies)
如果没有用户,它将重定向到您可以选择的某些 url 目的地。
这种验证会话的方法不是最好的方法,但它可以防止您的页面在通过客户端检查是否有用户时出现闪烁