【问题标题】:Next.js Opt out of Layout Component for specific pages from _app.jsNext.js 为 _app.js 中的特定页面选择退出布局组件
【发布时间】:2021-06-29 01:29:28
【问题描述】:

如何在_app.js 中不使用Layout component 包装特定页面?

例如,我有两个页面pages/homepages/about,现在我如何不包装我的pages/home 页面与Layout 组件?

pages/_app.js

import "../styles/globals.css";
import Layout from "../components/Layout";

function MyApp({ Component, pageProps }) {

      return (
        <Layout>
          <Component {...pageProps} />
        </Layout>
      );
  
}

export default MyApp;

我尝试过的:

pages/_app.js

function MyApp({ Component, pageProps }) {
  console.log(typeof Component); // gives me a function

  switch (Component) {
    case Home():
      return <Component {...pageProps} />;
    default:
      return (
        <Layout>
          <Component {...pageProps} />{" "}
        </Layout>
      );
  }
}

pages/home.js

import React from 'react';
 
const Home= () => {
  return (<div>Hello</div>);
};
 
export default Home;

【问题讨论】:

  • 所以你想在没有Layout的情况下渲染Home。并且除Home 之外的所有其他组件将由Layout 包装。对吗?
  • 是的,我正在使用 Next.js BTW。
  • 好的。你能分享一下MyApp函数被调用的代码吗?
  • Next.js 从_app.js 隐式调用它。但我想,我明白了,我必须使用switch (Component.name) { }

标签: javascript reactjs next.js server-side-rendering


【解决方案1】:

通过检查传递给它的appProps.router.pathname 属性。

方式 1

function MyApp({ Component, pageProps, ...appProps }: AppProps) {
  const getContent = () => {
    if ([`/dashboard`].includes(appProps.router.pathname))
      return <Component {...pageProps} />;

    return (
      <Layout>
        <Component {...pageProps} />{" "}
      </Layout>
    );
  };

  return <ApplicationWrapper>{getContent()}</ApplicationWrapper>;
}

方式 2

function MyApp({ Component, pageProps, ...appProps }: AppProps) {

    const isLayoutNeeded = [`/dashboard`].includes(appProps.router.pathname);

    const LayoutComponent = isLayoutNeeded ? Layout : React.Fragment;

    


  return (<ApplicationWrapper> 
    <LayoutComponent>
        <Component />
    </LayoutCompnent>
    </ApplicationWrapper>);
}

【讨论】:

  • 在开发模式下,“Component.name”获取名称,但是当我创建构建时,“Component.name”的值为空。知道为什么会这样吗?
  • 或许可以尝试添加对路线名称的检查?
  • @Gurveer 尝试添加displayName,而不是像我在下面的答案中指定的那样。它也适用于 React :)
【解决方案2】:

我认为Per-Page Layouts 有更简洁的方法。我目前通过为所有页面创建默认布局并为需要特定布局的页面(例如在我的登录和注册页面中)覆盖它来做到这一点。

    export default function LoginPage() {
      return {
        /** Some JSX */
      }
    }
    // Return the page without additional layout.
    LoginPage.getLayout = (page) => page

    export default function MyApp({ Component, pageProps }) {
      // Use the specified page layout or fallback to the default one.
      const getLayout = Component.getLayout ?? defaultPageLayout

      return getLayout(<Component {...pageProps} />)
    }

【讨论】:

    【解决方案3】:

    我使用displayName 静态属性。它也适用于任何 React.js 组件。

    const OGImagePreview = () => <h1>OG Image Preview</h1>
    
    OGImagePreview.displayName = 'OGImagePreview'
    
    export default OGImagePreview
    

    然后我在_app.tsx 中使用switch...case 就像:

    switch (Component.displayName) {
        case 'OGImagePreview':
            return (
                <>
                    <Component {...pageProps} />
                </>
            )
        default:
            return (
                <>
                    <Head>
                        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
                    </Head>
                    <ThemeProvider attribute="class" themes={['light', 'dark']}>
                        <Progress />
                        <Nav />
                        <Component {...pageProps} />
                    </ThemeProvider>
                    <ScrollToTop />
                    <Analytics />
                </>
            )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      • 2018-11-11
      • 2018-08-24
      • 1970-01-01
      • 2021-11-03
      • 1970-01-01
      • 2018-11-17
      相关资源
      最近更新 更多