如何使用WordPress在NextJS中管理导航菜单

如何使用WordPress在NextJS中管理导航菜单,wordpress,graphql,next.js,Wordpress,Graphql,Next.js,我正在使用无头WordPress和GraphQL构建一个NextJS应用程序。文档中不清楚我应该在哪里调用查询来创建站点导航。 导航由后端的WordPress菜单(外观>菜单)动态控制,我可以通过GraphQL成功访问这些菜单,而不会在index.js和posts/[slug].js中出现任何问题 // index.js export default function Index({ primaryMenu = [] }) { return ( <Layout>

我正在使用无头WordPress和GraphQL构建一个NextJS应用程序。文档中不清楚我应该在哪里调用查询来创建站点导航。

导航由后端的WordPress菜单(
外观>菜单
)动态控制,我可以通过GraphQL成功访问这些
菜单
,而不会在
index.js和
posts/[slug].js中出现任何问题

// index.js
export default function Index({ primaryMenu = [] }) {
   return (
     <Layout>
         <Header> 
          {primaryMenu.map((item, index) => {
             return (<a href={item.url}>{item.label}</a>)
          )}
         </Header>
     </Layout>
   );

}

export async function getStaticProps() {
  const primaryMenu = await getPrimaryMenu(); // Get menu via GraphQL
  return {
    props: { primaryMenu },
  };
}
//index.js
导出默认函数索引({primaryMenu=[]}){
返回(
{primaryMenu.map((项目,索引)=>{
返回()
)}
);
}
导出异步函数getStaticProps(){
const primaryMenu=wait getPrimaryMenu();//通过GraphQL获取菜单
返回{
道具:{primaryMenu},
};
}
我遇到的问题是,我在每个模板上重复了
getStaticProps
函数,我应该能够在
组件本身或其他方法中对此使用某种全局查询。我找不到关于如何执行此操作的文档,并且它在组件中不起作用


欢迎您提供有关全局查询(如动态导航查询)在NextJS应用程序中的位置的任何指导(或示例)。

有几种方法可以做到这一点:

  • 您可以在布局组件内使用@apollo/client中的useQuery()进行menuItems查询,以便其可用于布局内包装的所有页面。但问题是,这将有一个加载时间,并且数据不会像使用getServerSideProps()一样预取且随时可用(在页面级别)。因为这将在组件级别进行

    从“@apollo/client”导入{useQuery}

    导出默认函数布局(){

    const{loading,data}=useQuery(获取菜单查询) 返回{…} }

  • 您可以使用使用缓存策略的


  • 我曾与redux和wp rest为此争论过一段时间(对于JD站点),但我认为gql+apollo客户端的理论应该是一样的

    您需要使用扩展应用程序的自定义类覆盖下一个应用程序

    您可能需要使用HOC将apollo客户端的实例注入到AppContext中。之后需要建模

    编辑:()

    然后在你的应用程序getInitialProps中,你可以对get菜单进行查询。默认情况下,apollo客户端查询将获取缓存值,如果它已经在缓存存储中,我相信

      static async getInitialProps(appContext) {
        const { isServer,  pathname, apollo? } = appContext.ctx;
    
        // do menu query
        const menu = apollo.query???
    
        // Redux version
        // const state = store.getState();
        // let main_menu = state.menu;
        // if (!state.menu) {
        //  const menu = await apiService().getMenu("main");
        //  main_menu = menu;
        //  store.dispatch({ type: "SET_MENU", payload: menu });
        // }
    
        ...
    
        // call the page's `getInitialProps` and fills `appProps.pageProps`
        const initialProps = await App.getInitialProps(appContext);
    
        const appProps: any = {
          ...initialProps,
          menu: main_menu
        };
    
        return appProps;
    
      }
    
    现在菜单位于应用程序组件的页面道具中,可以向下传递。
    或者,您可以使用apollo客户端在子组件中再次进行查询。因此,当您在头文件或其他文件中再次进行查询时,如果是相同的查询,它将接受缓存响应

    我为包含模板名+post slug以及菜单项的菜单创建了一个端点,并将wp模板映射到下一个路由

    const menu = useSelector((state: any) => state.menu);
    const menuItems = menu.map((item: any) => {
        const path = getTemplatePath(item.template);
        return (
          <Link key={item.slug} href={`/${path}`} as={`/${item.slug}`} scroll={false}>
            <a>{item.title}</a>
          </Link>
        );
      });
    
    const菜单=使用选择器((状态:any)=>state.menu);
    const menuItems=menu.map((项目:任意)=>{
    const path=getTemplatePath(item.template);
    返回(
    {item.title}
    );
    });
    
    是的,
    getInitialProps
    确实有效,但NextJS文档似乎很快就会被弃用,所以我很犹豫是否使用它。@DarrenCooney在我这样做时不存在,所以我不知道。我不认为已弃用,但发出警告,因为它无法静态生成。因为包含它意味着需要重新生成数据请求在页面下。在本例中,这是正确的,因为它需要在呈现(即菜单)之前向WP请求数据。但仍然可以缓存和服务呈现的页面。我部署到现在(vercel)并在配置中添加了缓存和重新验证的标题。
    “标题”:{“缓存控制”:“s-maxage=1,在重新验证时过时”},
    const menu = useSelector((state: any) => state.menu);
    const menuItems = menu.map((item: any) => {
        const path = getTemplatePath(item.template);
        return (
          <Link key={item.slug} href={`/${path}`} as={`/${item.slug}`} scroll={false}>
            <a>{item.title}</a>
          </Link>
        );
      });