繁体   English   中英

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

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

我有一个身份验证上下文组件,我在其中包装了我的主要应用程序组件,但同时我也在尝试根据 Next.js 文档在此处执行页面特定布局组件:https://nextjs.org/docs/basic-features /layouts#per-page-layouts

我这样做是否正确,因为我似乎无法从我的上下文提供程序获取数据。

/上下文/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

function MyApp({ Component, pageProps }) {    

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

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

export default MyApp;

/组件/项目/List.js

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

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

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

export default ProjectList;

我正在尝试控制台登录用户,但它给了我未定义的信息。 我在想这是因为它作为布局组件的包装方式? 我可能做错了。 但是我在我的AuthContext中为用户做了控制台登录,那里的信息是正确的。

/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>;
};

当我删除Projects.getLayout代码块时,数据又回来了,但是当我添加这段代码时,数据就消失了。

/组件/项目/Layout.js

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

export default ProjectLayout

使用您当前的结构ProjectLayout不会被AuthContext包裹,这意味着您将无法访问其上下文。

您可以修改_app的结构并移动getLayout调用,以便上下文正确包装它。

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

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

请注意,如果getLayout function 使用挂钩或依赖于父元素的内容,则在 Context 中调用getLayout可能会导致错误。

它将首先调用getLayout然后调用上下文,因此它的值最初将是默认(后备)值(就像执行foo(bar())并期望foo将在bar之前被调用)。

为了避免这种情况,直接返回组件(使用getLayout作为生成组件的 function):

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

或将布局用作组件:

// /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>
  );
}

编辑:没有 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM