简体   繁体   English

Next.js 上下文提供程序包装 App 组件,页面特定的布局组件提供未定义的数据

[英]Next.js context provider wrapping App component with page specific layout component giving undefined data

I have an auth context component where I'm wrapping my main app component, but at the same time I'm also trying to do page specific layout component per Next.js documentation here:https://nextjs.org/docs/basic-features/layouts#per-page-layouts我有一个身份验证上下文组件,我在其中包装了我的主要应用程序组件,但同时我也在尝试根据 Next.js 文档在此处执行页面特定布局组件:https://nextjs.org/docs/basic-features /layouts#per-page-layouts

Am I doing this correctly, because I can't seem to be getting the data from my Context provider.我这样做是否正确,因为我似乎无法从我的上下文提供程序获取数据。

/context/AuthContext.js /上下文/AuthContext.js

const UserContext = createContext({});

export default function AuthContext({children}) {
  // .. code
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

export const useUser = () => useContext(UserContext);

/_app.js /_app.js

function MyApp({ Component, pageProps }) {    

  const getLayout = Component.getLayout || ((page) => page);

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

export default MyApp;

/components/Project/List.js /组件/项目/List.js

import { useUser } from "../../context/AuthContext";

const ProjectList = () => {
  const { user } = useUser();
  console.log("get user data", user);

  return (
    <>
      test
    </>
  );
};

export default ProjectList;

I'm trying to console log the user, but it's giving me undefined.我正在尝试控制台登录用户,但它给了我未定义的信息。 I'm thinking it's because the way it's wrapped as a layout component?我在想这是因为它作为布局组件的包装方式? I could be doing this wrong.我可能做错了。 But I did console log inside my AuthContext for user, and the information there is correct.但是我在我的AuthContext中为用户做了控制台登录,那里的信息是正确的。

/pages/projects/index.js /pages/projects/index.js

const Projects = () => {
  // code goes here
  return (
    <div>
      code goes here
    </div> 
  )
}

export default Projects;

Projects.getLayout = function getLayout(page) {
  return <ProjectLayout>{page}</ProjectLayout>;
};

When I remove the Projects.getLayout block of code, the data comes back, but when I add this code, data is gone.当我删除Projects.getLayout代码块时,数据又回来了,但是当我添加这段代码时,数据就消失了。

/components/Project/Layout.js /组件/项目/Layout.js

const ProjectLayout = ({children}) => {
  return (
    <>
      <ProjectList />
      {children}
    </>
  }

export default ProjectLayout

With your current structure ProjectLayout isn't getting wrapped by the AuthContext , meaning you won't have access to its context.使用您当前的结构ProjectLayout不会被AuthContext包裹,这意味着您将无法访问其上下文。

You can modify your _app 's structure and move the getLayout call around so that the context wraps it properly.您可以修改_app的结构并移动getLayout调用,以便上下文正确包装它。

function MyApp({ Component, pageProps }) {    
    const getLayout = Component.getLayout || ((page) => page);

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

Note that calling getLayout inside the Context could lead to errors if the getLayout function uses hooks or stuff that depends on a parent element .请注意,如果getLayout function 使用挂钩或依赖于父元素的内容,则在 Context 中调用getLayout可能会导致错误。

It will be calling getLayout first and then the context, so the value of it will be initially the default (fallback) value (it's like doing foo(bar()) and expecting that foo will be called before bar ).它将首先调用getLayout然后调用上下文,因此它的值最初将是默认(后备)值(就像执行foo(bar())并期望foo将在bar之前被调用)。

To avoid this, return directly the component (using getLayout as a function that generates a component):为了避免这种情况,直接返回组件(使用getLayout作为生成组件的 function):

// /pages/projects/index.js
Projects.getLayout = (children) => (
  // can't use hooks here, return the component immediately
  <ProjectLayout>{children}</ProjectLayout>;
);

or use the layout as a component:或将布局用作组件:

// /pages/projects/index.js
Projects.Layout = ({ children }) => {
  return <ProjectLayout>{children}</ProjectLayout>;
};

// /pages/_app.js
export default function App({ Component, pageProps }) {    
  const Layout = Component.Layout || (({ children }) => children);
  return (
     <AuthContext>
       <Layout>
          <Component {...pageProps} />
       </Layout>
     </AuthContext>
  );
}

Edit: The difference is more visible without JSX编辑:没有 JSX 时差异更明显

// incorrect
return React.createElement(AuthContext, null,
  // getLayout is called before AuthContext
  getLayout(
    React.createElement(Component, pageProps)
  )
)

// correct
return React.createElement(AuthContext, null,
  // Layout is called after AuthContext
  React.createElement(Layout, null,
    React.createElement(Component, pageProps)
  )
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Next.js 选择退出 _app.js 中特定页面的布局组件 - Next.js Opt out of Layout Component for specific pages from _app.js 全局布局组件中的next.js getInitialProps - next.js getInitialProps in a global layout component _app.js class 组件 Next.js 中的上下文 API 调度(消费者) - Context API dispatch (consumer) in _app.js class component Next.js 用它包装我的应用程序组件时 Context.provider 抛出错误 - Context.provider throw error when wrapping my app component with it Next.js - 页面未将 GetServerSideProps 放入页面组件道具中(使用自定义 _app.js) - Next.js - Page not getting GetServerSideProps into Page component props (with custom _app.js) 在Next.JS 6中使用_app.js页面组件时,转换触发得太早了 - Transitions are firing too early when using _app.js page component in Next.JS 6 使用上下文包装应用程序组件并获取 TypeError: (destructured parameter) is undefined - Wrapping the app component with a context and getting the TypeError: (destructured parameter) is undefined 等待_app.js加载,然后在Next.js上运行组件 - Wait _app.js loaded then run component on Next.js 在 React/Next.js 中,如何简单地将数据从一个页面的组件传递到另一个页面上的组件? - How can I simply pass data from a component one page to a component on another page in React/Next.js? 在页面加载时将道具传递给子组件 - 与 next.js 反应 - Pass props to a child component on page load - react with next.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM