我如何全局指定身份验证而不是在 Next js 的每个页面上定义,我正在使用 next-auth 包和 react 查询
How can I specify authentication globally instead of defining on every page in Next js, I am using next-auth package with react query
现在,我在每个页面上都使用身份验证,但我想在 _app.tsx 文件中全局定义它。
现在,我的组件
const Home: NextPage = () => {
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />
}
return (
<p>You are signed In </p>
)
};
useAuth 是一个提供会话对象的自定义钩子,它使用 react-query
export function useAuth(refreshInterval?: number) {
const { error, data } = useQuery("sessionURL", fetchSession, {
refetchOnWindowFocus: true,
refetchOnMount: true,
refetchOnReconnect: true,
refetchInterval: refreshInterval || 25000,
});
return {
session: data,
loading: typeof data === "undefined" && typeof error === "undefined",
};
}
_app.tsx
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
</QueryClientProvider>
);
}
使用这种方法,我必须在每个组件中定义 Unauthenticated 路由。我想在 _app.tsx 中全局定义它,如下所示
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
import { useAuth } from "../utils/Hooks";
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />
}
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
</QueryClientProvider>
);
}
export default MyApp;
但是 问题是 useAuth 在其中使用了 useQuery 并且它给出了合法的包装错误。
我怎样才能让它工作,有没有什么方法可以全局定义身份验证???
所以我认为为此你应该创建一个包装器组件,它自己进行检查然后呈现出来,这样你就不需要为每个页面重复它。
// AuthWrapper.tsx
import UnAuthenticated from "./UnAuthenticated";
import useAuth from "../hooks/useAuth";
import { PropsWithChildren } from "react";
const AuthWrapper = ({ children }: PropsWithChildren<{}>) => {
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />;
}
return <>{children}</>;
};
export default AuthWrapper;
然后像这样在_app.tsx
中使用它(感谢@Janik)
你甚至可以通过这个小技巧来阻止某些页面进行身份验证
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
import { useAuth } from "../utils/Hooks";
import { useRouter } from "next/router";
import AuthWrapper from "../components/AuthProvider";
// Pages that don't require auth
const publicPages = ["/sign-in", "/sign-up"]; // or more if you want
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
const router = useRouter();
const isPublicPage = publicPages.includes(router.pathname);
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
{isPublicPage ? (
<Component {...pageProps} />
) : (
<AuthWrapper>
<Component {...pageProps} />
</AuthWrapper>
)}
</SessionProvider>
</QueryClientProvider>
);
}
export default MyApp;
现在,我在每个页面上都使用身份验证,但我想在 _app.tsx 文件中全局定义它。
现在,我的组件
const Home: NextPage = () => {
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />
}
return (
<p>You are signed In </p>
)
};
useAuth 是一个提供会话对象的自定义钩子,它使用 react-query
export function useAuth(refreshInterval?: number) {
const { error, data } = useQuery("sessionURL", fetchSession, {
refetchOnWindowFocus: true,
refetchOnMount: true,
refetchOnReconnect: true,
refetchInterval: refreshInterval || 25000,
});
return {
session: data,
loading: typeof data === "undefined" && typeof error === "undefined",
};
}
_app.tsx
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
</QueryClientProvider>
);
}
使用这种方法,我必须在每个组件中定义 Unauthenticated 路由。我想在 _app.tsx 中全局定义它,如下所示
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
import { useAuth } from "../utils/Hooks";
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />
}
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
</QueryClientProvider>
);
}
export default MyApp;
但是 问题是 useAuth 在其中使用了 useQuery 并且它给出了合法的包装错误。
我怎样才能让它工作,有没有什么方法可以全局定义身份验证???
所以我认为为此你应该创建一个包装器组件,它自己进行检查然后呈现出来,这样你就不需要为每个页面重复它。
// AuthWrapper.tsx
import UnAuthenticated from "./UnAuthenticated";
import useAuth from "../hooks/useAuth";
import { PropsWithChildren } from "react";
const AuthWrapper = ({ children }: PropsWithChildren<{}>) => {
const { session, loading } = useAuth();
if (!session) {
return <UnAuthenticated />;
}
return <>{children}</>;
};
export default AuthWrapper;
然后像这样在_app.tsx
中使用它(感谢@Janik)
你甚至可以通过这个小技巧来阻止某些页面进行身份验证
import { SessionProvider } from "next-auth/react";
import { QueryClient, QueryClientProvider } from "react-query";
import { useAuth } from "../utils/Hooks";
import { useRouter } from "next/router";
import AuthWrapper from "../components/AuthProvider";
// Pages that don't require auth
const publicPages = ["/sign-in", "/sign-up"]; // or more if you want
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const queryClient = new QueryClient();
const router = useRouter();
const isPublicPage = publicPages.includes(router.pathname);
return (
<QueryClientProvider client={queryClient}>
<SessionProvider session={session}>
{isPublicPage ? (
<Component {...pageProps} />
) : (
<AuthWrapper>
<Component {...pageProps} />
</AuthWrapper>
)}
</SessionProvider>
</QueryClientProvider>
);
}
export default MyApp;