[英]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.