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

6
我正在使用GraphQL和WordPress无头模式构建NextJS应用程序。但是,从文档中无法清楚地知道在哪里调用查询以创建站点导航。站点导航由WordPress菜单(“外观”>“菜单”)在后端动态控制,我可以在Next JS的index.js和posts / [slug] .js页面模板上成功访问这些menuItems,而且没有任何问题。参考链接:https://github.com/lfades/next.js/tree/examples/cms-wordpress/examples/cms-wordpress
// 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函数,我应该能够使用某种全局查询来解决这个问题,可以在<header/>组件本身或另一种方法中实现。 我找不到如何做到这一点的文档,并且在组件中无法正常工作。
欢迎提供任何指导(或示例),关于在NextJS应用程序中存储全局查询(例如动态导航查询)的位置。
2个回答

1

有几种方法可以实现:

  1. 您可以使用 Layout 组件内的 useQuery() 从 @apollo/client 进行 menuItems 查询,以便在包装在 Layout 中的所有页面中都可用。但是,这样做的问题是,将会有加载时间,并且数据不会像我们在页面级别上使用 getServerSideProps() 那样被预取和立即可用。因为这将是在组件级别上。

    import { useQuery } from "@apollo/client";

    export default function Layout () {

    const { loading, data } = useQuery( GET_MENU_QUERY ) return {...} }

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


0

我曾经在JD网站上使用redux和wp rest进行了一段时间的战斗,但我认为对于gql + apollo客户端来说理论应该是相同的。

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

您可能需要使用HOC将apollo客户端的实例注入到AppContext中。 我使用了Redux的这个包装器。需要按照那个模型进行建模。

编辑:(看起来有人已经做好了

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

然后在您的应用程序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组件的页面属性中,可以向下传递。
或者您可以使用Apollo客户端在子组件中再次进行查询。因此,当您再次进行查询时,在标题或其他位置,它将获取缓存的响应,前提是查询相同。

我为包括模板名称+文章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 文档似乎暗示它很快会被弃用,所以我不太敢使用它。 https://nextjs.org/docs/api-reference/data-fetching/getInitialProps - Darren Cooney
@DarrenCooney 当我做这个的时候,那还不存在,所以我不知道。我认为它不是被弃用了,而是因为它不能再静态生成了而受到警告。因为包含它意味着需要数据请求来渲染页面。在这种情况下,它确实需要正确地执行,因为它需要在渲染之前向 WP 请求数据(即菜单)。 - hyperdrive
但仍然可以缓存和提供渲染后的页面。我部署到now(vercel),并在配置中添加了缓存和重新验证的标头。 "headers": { "cache-control": "s-maxage=1,stale-while-revalidate" }, - hyperdrive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接