【问题标题】:How to Manage a Navigation Menu in NextJS with WordPress如何使用 WordPress 在 NextJS 中管理导航菜单
【发布时间】:2020-12-09 05:24:48
【问题描述】:

我正在使用带有 GraphQL 的无头 WordPress 构建 NextJS 应用程序。从文档中不清楚我应该在哪里调用查询来创建站点导航。 https://github.com/lfades/next.js/tree/examples/cms-wordpress/examples/cms-wordpress

导航由后端的 WordPress 菜单 (Appearance > Menus) 动态控制,我可以通过 GraphQL 成功访问这些 menuItems,在 Next JS 中的 index.jsposts/[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 },
  };
}

我遇到的问题是我在每个模板上重复 getStaticProps 函数,我应该能够为此使用某种全局查询,无论是在 &lt;header/&gt; 组件本身还是其他方法中。我找不到有关如何执行此操作的文档,并且它在组件中不起作用。

感谢任何有关全局查询(例如动态导航查询)在 NextJS 应用中的位置的指导(或示例)。

【问题讨论】:

    标签: wordpress graphql next.js


    【解决方案1】:

    有几种方法可以做到:

    1. 您可以在 Layout 组件内使用来自 @apollo/client 的 useQuery() 进行 menuItems 查询,以便它可用于包装在 Layout 内的所有页面。然而,这样做的问题是,会有一个加载时间,并且数据不会像我们可以使用 getServerSideProps() (在页面级别)那样被预取并且随时可用。因为这将在组件级别。

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

      导出默认函数Layout(){

      const { 加载,数据 } = useQuery( GET_MENU_QUERY ) 返回 {...} }

    2. 您可以使用使用缓存策略的swr。有blog解释了如何使用它

    【讨论】:

      【解决方案2】:

      我用 redux 和 wp 休息了一段时间(对于 JD 站点),但我认为对于 gql + apollo 客户端的理论应该是相同的。

      您需要使用扩展 App 的自定义类覆盖 Next App _app。

      您可能需要使用 HOC 将 apollo 客户端的实例注入 AppContext。 I used this wrapper for Redux。之后需要建模。

      编辑:(Looks like someone has made it already)

      // export default withRedux(makeStore)(MyApp);
      export default withApollo(apolloClient)(MyApp); ???
      

      然后在您的 App getInitialProps 中,您可以查询获取菜单。默认情况下,如果我相信 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;
      
        }
      

      现在菜单在App Component的页面props中,可以向下传递。
      或者您可以使用 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>
          );
        });
      

      【讨论】:

      • 是的,getInitialProps 确实有效,但是 NextJS 文档让它看起来很快就会被弃用,所以我很犹豫要不要使用它。 nextjs.org/docs/api-reference/data-fetching/getInitialProps
      • @DarrenCooney 我这样做的时候不存在,所以我不知道。我不认为已弃用,但警告,因为它不能再静态生成。因为包含它意味着需要数据请求来呈现页面。在这种情况下它是正确的,因为它需要在渲染之前向 WP 询问数据(即菜单)。
      • 但是仍然可以缓存和提供渲染页面。我部署到 now(vercel) 并在配置中添加了要缓存和重新验证的标头。 "headers": { "cache-control": "s-maxage=1,stale-while-revalidate" },
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多