Darren Cooney
Estoy creando una aplicación NextJS usando WordPress sin cabeza con GraphQL. No está claro en la documentación dónde debo llamar a la consulta para crear la navegación del sitio.
https://github.com/lfades/next.js/tree/examples/cms-wordpress/examples/cms-wordpress
La navegación es controlada dinámicamente por los menús de WordPress (Appearance > Menus
) en el backend y puedo acceder con éxito a estos menuItems
a través de GraphQL sin ningún problema en el index.js
y posts/[slug].js
plantillas de página en Next 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 },
};
}
El problema que tengo con esto es que estoy repitiendo el getStaticProps
función en cada plantilla y debería poder usar algún tipo de consulta global para esto, ya sea en el <header/>
componente en sí mismo u otro método. No puedo encontrar documentación sobre cómo hacer esto y no funciona en componentes.
Se agradece cualquier orientación (o ejemplo) sobre dónde viviría una consulta global, como una consulta de navegación dinámica, en una aplicación NextJS.
Hay un par de formas en las que puedes hacerlo:
-
Puede consultar menuItems con useQuery() desde @apollo/client dentro del componente Diseño para que esté disponible para todas las páginas que están envueltas dentro del Diseño. Sin embargo, el problema con esto es que habrá un tiempo de carga y los datos no se buscarán previamente ni estarán fácilmente disponibles como podemos hacer con getServerSideProps() (a nivel de página). Porque esto será a nivel de componente.
importar { useQuery } de “@apollo/cliente”;
Exportar función predeterminada Diseño () {
const { cargando, datos } = useQuery( GET_MENU_QUERY ) return {…} }
-
Puedes usar swr que utiliza la estrategia de almacenamiento en caché. Hay Blog eso explica como usarlo
hiperimpulsor
Luché contra esto por un tiempo (para el sitio JD) con redux y wp rest, pero creo que la teoría debería ser la misma para el cliente gql + apollo.
Debe anular Next App _app con una clase personalizada que amplíe App.
Y es posible que deba inyectar una instancia del cliente apollo en AppContext usando un HOC. Usé este envoltorio para Redux. Tendría que ser modelado después de eso.
Editar: (Parece que alguien ya lo ha hecho)
// export default withRedux(makeStore)(MyApp);
export default withApollo(apolloClient)(MyApp); ???
Luego, en su aplicación getInitialProps, puede hacer una consulta para obtener el menú. Por defecto, la consulta del cliente de apolo tomará el valor almacenado en caché si ya está en el almacén de caché, creo.
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;
}
Ahora el menú está en los accesorios de la página del componente de la aplicación, que se puede transmitir.
O puede usar el cliente apollo para hacer la consulta nuevamente en un componente secundario. Entonces, cuando vuelva a realizar la consulta, en el encabezado o lo que sea, tomará la respuesta almacenada en caché siempre que sea la misma consulta.
Hice un punto final para los menús que incluían el nombre de la plantilla + el slug de la publicación junto con los elementos del menú y asigné las plantillas de wp a las siguientes rutas.
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>
);
});
-
Sí,
getInitialProps
funciona, pero los documentos de NextJS hacen que parezca que pronto quedará obsoleto, por lo que dudo en usarlo. nextjs.org/docs/api-reference/data-fetching/getInitialProps– Darren Cooney
10 sep 2020 a las 19:26
-
@DarrenCooney Eso no existía cuando hice esto, así que no lo sé. No creo que esté obsoleto, pero advertido porque ya no puede generar estáticamente. Porque incluirlo significa que se requieren solicitudes de datos para representar las páginas. Lo que en este caso hace bien, porque necesita pedirle datos a WP antes de renderizar (es decir, el menú).
– hiperimpulsor
10 sep 2020 a las 19:46
-
Pero aún es posible almacenar en caché y servir páginas renderizadas. Implementé ahora (vercel) y en la configuración agregué los encabezados para almacenar en caché y revalidar.
"headers": { "cache-control": "s-maxage=1,stale-while-revalidate" },
– hiperimpulsor
10 sep 2020 a las 19:47