我如何在Next.js 13中检测它是否是404页面

2j4z5cfb  于 2023-06-22  发布在  其他
关注(0)|答案(2)|浏览(224)

我有一个客户端组件,它检查身份验证状态,并被合并到app/layout.tsx中。目标是确定用户是否已登录。否则,如果当前URL路径不是/login,则用户将被重定向到登录页面。如果用户已登录,如果当前URL路径为/login,则用户将重定向到/。代码如下:
(Firebase)

onAuthStateChanged(auth, (user) => {
  if (user) {  // if user is logged in
    if (path === "/login") {
      router.push("/");
    }
  } else { // if user is not logged in
    if (path !== "/login") {
      router.push("/login");
    }
  }
});

请注意,使用此代码,如果用户未登录,则无法访问任何404页面。如果用户这样做,代码将重定向到登录页面,这是我不希望的。为了防止这种情况,我需要检测它是否是一个404页面。
那么,我如何检查它是否是Next.js 13的404页面?
如果您需要任何其他信息来解决问题,请告诉我。

vzgqcmou

vzgqcmou1#

Next.js和错误处理

Next.js中,内置的错误页面组件_error.js_error.tsx位于/pages目录中,处理所有错误代码,包括404。但是,它并没有直接提供一种机制来检查当前页面是否是来自另一个组件的404。
一个可能的解决方案是在根组件layout.tsx中设置一个状态,每当Error页面组件被触发时,该状态就会改变。您可以通过React上下文或您选择的状态管理库来实现这一点。
让我们继续我的方法:
首先,我们需要构建一个上下文。我为这个案例创建了一个NotFoundContext

验证码:

// Import the necessary React hooks
import { createContext, useContext, useState } from 'react';

// Define our NotFoundContext context
const NotFoundContext = createContext();

// Provide a Provider function that holds our state
export function NotFoundProvider({ children }) {
  // Define state variable to track 404 status
  const [isNotFound, setNotFound] = useState(false);

  // Use Provider to allow children components access to our 404 state
  return (
    <NotFoundContext.Provider value={{ isNotFound, setNotFound }}>
      {children}
    </NotFoundContext.Provider>
  );
}

// A hook for easy access to the NotFoundContext
export function useNotFound() {
  return useContext(NotFoundContext);
}

现在我们需要用我们定义的NotFoundProvider Package 应用程序。

验证码:

// Import NotFoundProvider context
import { NotFoundProvider } from './NotFoundContext';

// Define your Application
function MyApp({ Component, pageProps }) {
  return (
    // Provide the NotFound context to the entire Application
    <NotFoundProvider>
      <Component {...pageProps} />
    </NotFoundProvider>
  );
}

export default MyApp;

我们需要调整_error.js_error.tsx以反映isNotFound状态。只需在jstsx文件中将isNotFound设置为true即可。

验证码:

// Import useNotFound hook
import { useNotFound } from '../NotFoundContext';
import { useEffect } from 'react';

function Error({ statusCode }) {
  // Obtain our function for setting NotFound state
  const { setNotFound } = useNotFound();

  // Till component mount, check if statusCode is 404 and adjust NotFound state
  useEffect(() => {
    setNotFound(statusCode === 404);
  }, [statusCode]);

  // TODO: Rest of this component
}

// Get statusCode from server response or the error object itself
Error.getInitialProps = ({ res, err }) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;

现在,isNotFound可以在您自己的组件中访问和使用。

验证码:

// Import our custom hook
import { useNotFound } from './NotFoundContext';
import { onAuthStateChanged } from 'firebase/auth';

// Other code

onAuthStateChanged(auth, (user) => {
  // Obtain our NotFound state value
  const { isNotFound } = useNotFound();
  
  if (user) { // User is logged in
    if (path === "/login") {
      router.push("/");
    }
  } else if (!isNotFound) { // User is not logged in and the page is not a 404 status
    if (path !== "/login") {
      router.push("/login");
    }
  }
});

我希望这对你有帮助!

am46iovg

am46iovg2#

通常,重定向或身份验证在中间件文件或 Package 文件中处理。如果您仍然希望遵循您的方法,则应在应用程序中手动定义所有路由

const routes=["route1",....]

onAuthStateChanged(auth, (user) => {
  if (user) {  // if user is logged in
    if (path === "/login") {
      router.push("/");
    }
  } else { // if user is not logged in
    // if not logged in and visiting a valid path
    if (routes.includes(path)) {
      router.push("/login");
    }
  }
});

相关问题