如何使用 Next.js 仅将某些页面包装在上下文提供程序中?

问题描述 投票:0回答:7

我想在三个页面之间共享数据(这些是网络应用程序的核心),但我还有一堆不关心这些数据的博客页面。我看过的所有地方都建议将提供程序放入

_app.tsx
文件中。如果我理解正确的话,如果我将
MyApp
与提供程序一起包装,如果有人直接访问 www.myurl.com/blog/my-blog-1 (来自谷歌),这将导致提供程序运行其功能;即使该页面不会调用 useContext

如何在 Provider 中只包含三个页面并省略博客页面?

例如:

这是我的

_app.tsx
的样子:

import { AppProps } from 'next/app'
import '../styles/index.css'

export default function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}
reactjs react-hooks next.js use-context
7个回答
10
投票

聚会有点晚了,但实际上有一个官方方法可以做到这一点: 使用每页布局。 首先稍微调整你的

_app.tsx
文件:

import type { ReactElement, ReactNode } from 'react';
import { AppProps } from 'next/app';
import type { NextPage } from 'next';

type NextPageWithLayout = NextPage & {
    getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
    Component: NextPageWithLayout;
};
export const App = ({ Component, pageProps }: AppPropsWithLayout): unknown => {

    // Use the custom layout defined at the page level, if available
    const getLayout = Component.getLayout ?? ((page) => page);

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

然后在页面组件中写入以下内容:

// DashboardPage.ts that need to have a UserProvider and CompanyProvider
import Layout from '@components/Layout'; // Default Layout that is imported for all the page
import { ReactElement } from 'react';
import { UserProvider } from '@contexts/user';
import { CompanyProvider } from '@contexts/company';

const DashboardPage = (): JSX.Element => {
    return <DashboardContainer />;
};

// Custom Layout to wrap the page within the User and company providers
DashboardPage.getLayout = function getLayout(page: ReactElement) {
    return (
        <Layout title="Dashboard page">
            <UserProvider>
                <CompanyProvider>{page}</CompanyProvider>
            </UserProvider>
        </Layout>
    );
};

export default DashboardPage;


3
投票

嗯,这是一个有趣的问题。

挑战在于 Next 实现基于文件的路由的方式。由于无法为页面组创建包装器,因此您唯一能做的就是将应用程序包装在上下文提供程序中。但这并不能真正解决您的问题。

SOOO...我认为有一个解决方法。如果您希望能够在上下文提供程序中包装特定的一组页面,首先,您需要将基于文件的路由器替换为react-router。

Andrea Carraro 有一篇关于这个主题的非常有趣的文章。我认为你应该尝试一下: https://dev.to/tooomuchdesign/next-js-react-router-2kl8

我也会尝试寻找另一种解决方案,但请告诉我这对你有用吗。


1
投票

有一种解决方法可以使用包装器包装特定路径的组件,而无需使用反应路由器。 看看这个视频: https://www.youtube.com/watch?v=69-mnojSa0M

该视频向您展示了如何使用嵌套布局包装子路径的组件。创建一个嵌套布局并使用您的上下文提供程序包装该布局。


0
投票

我对 Next.js 很陌生,正在寻找同样的问题。 也许我们可以只使用

pathname
钩子中的
query
useRouter
并在我们的
Contexts
或自定义
_app

中尝试一些条件语句

下一个/路由器


0
投票

很晚才回答我的问题,但我的方法可能会对将来的某人有所帮助。 我使用页面作为包装器,并使用查询参数进行导航。


例如


0
投票

我使用 contextProvider 并检查 _app.js 中的路径页面

myContextProvider.js

import React, { useState } from 'react';
const Context = React.createContext({});

export function myContextProvider({ children }) {
     const [ state1, setState1 ] = useState(true);

     return <Context.Provider value={{ state1, setState1 }}>
          {children} 
     </Context.Provider>;
}

export default Context;

_app.js

import { useRouter } from 'youreFavoRouter';
import { myContextProvider } from './myContextProvider.js';

export default function MyApp({ Component, pageProps }) {
    const router = useRouter();
    
    const isBlogPage = router.pathname.includes('blog');

    return (
        <div>
            {isBlogPage ? (
                <Component {...pageProps} />
            ) : (
                <myContextProvider>
                    <Component {...pageProps} />
                </myContextProvider>
            )}
        </div>
    );
}

现在 myContextProvider 上的所有状态和函数都可以在您选择的页面上查看和使用。 我希望能帮助任何人。 :)


0
投票

嘿,我想我应该发布这个我发现到目前为止对我有用的解决方案。我想也许我可以将我的上下文导入到我的一个页面中,并测试用它包装提供程序是否可行。我也是 Nextjs 的新手,不知道这是否是一种合理的方法,但它似乎对我有用。我可以从我的 [用户名].tsx 页面中的这个组件用户配置文件访问我提供的所有内容。

如果这不是一个好的方法,任何反馈都会有用。

   // pages/[username].tsx
   import { UserProfile } from '@component/app/userprofile';


   const UserPage = () => {
   const router = useRouter();
   const { username } = router.query;

   useEffect(() => {
    
   console.log('Username:', username);
    }, [username]);

   return (
     <SampleContextProviderComponent>
       {user && user.map((user, index) => {
          if(username === user.username){

          return <UserProfile key={index} user={user}/>
          }
        })}
  
     </SampleContextProviderComponent>
     );
    };

    export default UserPage;
© www.soinside.com 2019 - 2024. All rights reserved.