Use
getStaticPropsygetServerSidePropscomo Hooks React
next-data-hooks es un LIB pequeño y simple que le permite escribir ganchos React para consultas de datos en Next.js levantando accesorios estáticos en el contexto React.
import { createDataHook } from 'next-data-hooks' ;
const useBlogPost = createDataHook ( 'BlogPost' , async ( context ) => {
const { slug } = context . params ;
return ; // ... get the blog post
} ) ;
function BlogPost ( ) {
const { title , content } = useBlogPost ( ) ;
return (
< >
< h1 > { title } </ h1 >
< p > { content } </ p >
</ >
) ;
}
BlogPost . dataHooks = [ useBlogPost ] ;
export default BlogPost ; Lo principal que ofrece esta biblioteca es un patrón que organiza getStaticProps / getServerSideProps .
Vea esta pregunta: ¿Por qué no se parametrizan los ganchos de datos?
Vea el ejemplo en este repositorio de algunas ideas sobre cómo organizar sus llamadas de datos estáticos utilizando este gancho.
npm i next-data-hooks
o
yarn add next-data-hooks
En la raíz, agregue un archivo .babelrc que contenga lo siguiente:
{
"presets" : [ " next/babel " ],
"plugins" : [ " next-data-hooks/babel " ]
}
️ No olvides este paso. Esto permite la eliminación del código para eliminar el código del lado del servidor en el código del cliente.
_app.tsx o _app.js import { AppProps } from 'next/app' ;
import { NextDataHooksProvider } from 'next-data-hooks' ;
function App ( { Component , pageProps } : AppProps ) {
const { children , ... rest } = pageProps ;
return (
< NextDataHooksProvider { ... rest } >
< Component { ... rest } > { children } </ Component >
</ NextDataHooksProvider >
) ;
} import { createDataHook } from 'next-data-hooks' ;
// this context is the GetStaticPropsContext from 'next'
// ?
const useBlogPost = createDataHook ( 'BlogPost' , async ( context ) => {
const slug = context . params ?. slug as string ;
// do something async to grab the data your component needs
const blogPost = /* ... */ ;
return blogPost ;
} ) ;
export default useBlogPost ;Nota: Para los usuarios de TypeScript, si está planeando usar solo el gancho de datos en el contexto de
getServerSideProps, puede importar el tipo de protección de tipo proporcionado,isServerSidePropsContext, para reducir el tipo del contexto entrante.
import { createDataHook , isServerSidePropsContext } from 'next-data-hooks' ;
const useServerSideData = createDataHook ( 'Data' , async ( context ) => {
if ( ! isServerSidePropsContext ( context ) ) {
throw new Error ( 'This data hook only works in getServerSideProps.' ) ;
}
// here, the type of `context` has been narrowed to the server side conext
const query = context . req . query ;
} ) ;
export default useServerSideData ; import ComponentThatUsesDataHooks from '..' ;
import useBlogPost from '..' ;
import useOtherDataHook from '..' ;
function BlogPostComponent ( ) {
const { title , content } = useBlogPost ( ) ;
const { other , data } = useOtherDataHook ( ) ;
return (
< article >
< h1 > { title } </ h1 >
< p > { content } </ p >
< p >
{ other } { data }
</ p >
</ article >
) ;
}
// compose together other data hooks
BlogPostComponent . dataHooks = [
... ComponentThatUsesDataHooks . dataHooks ,
useOtherDataHooks ,
useBlogPost ,
] ;
export default BlogPostComponent ;getStaticProps o getServerSideProps . import { getDataHooksProps } from 'next-data-hooks' ;
import { GetStaticPaths , GetStaticProps } from 'next' ;
import BlogPostComponent from '..' ;
export const getStaticPaths : GetStaticPaths = async ( context ) => {
// return static paths...
} ;
// NOTE: this will also work with `getServerSideProps`
export const getStaticProps : GetStaticProps = async ( context ) => {
const dataHooksProps = await getDataHooksProps ( {
context ,
// this is an array of all data hooks from the `dataHooks` static prop.
// ???
dataHooks : BlogPostComponent . dataHooks ,
} ) ;
return {
props : {
// spread the props required by next-data-hooks
... dataHooksProps ,
// add additional props to Next.js here
} ,
} ;
} ;
export default BlogPostComponent ; routes separado Next.js tiene un mecanismo de enrutamiento basado en archivos muy obstinado que no le permite colocar un archivo en la carpeta /pages sin que se considere una página.
En pocas palabras, esto no permite mucha organización.
Con next-data-hooks , puede tratar la carpeta /pages como una carpeta de puntos de entrada y organizar archivos en otro lugar.
my-project
# think of the pages folder as entry points to your routes
├── pages
│ ├── blog
│ │ ├── [slug].ts
│ │ └── index.ts
│ └── shop
│ ├── category
│ │ └── [slug].ts
│ ├── index.ts
│ └── product
│ └── [slug].ts
|
# think of each route folder as its own app with it's own components and helpers
└── routes
├── blog
│ ├── components
│ │ ├── blog-index.tsx
│ │ ├── blog-post-card.tsx
│ │ └── blog-post.tsx
│ └── helpers
│ └── example-blog-helper.ts
└── shop
├── components
│ ├── category.tsx
│ ├── product-description.tsx
│ └── product.tsx
└── helpers
└── example-shop-helper.ts
/routes/blog/components/blog-post.tsx import { createDataHook } from 'next-data-hooks' ;
// write your data hook in a co-located place
const useBlogPostData = createDataHook ( 'BlogPost' , async ( context ) => {
const blogPostData = // get blog post data…
return blogPostData ;
} ) ;
function BlogPost ( ) {
// use it in the component
const { title , content } = useBlogPostData ( ) ;
return (
< article >
< h1 > { title } </ h1 >
< p > { content } </ p >
</ article >
) ;
}
BlogPost . dataHooks = [ useBlogPostData ] ;
export default BlogPost ; /pages/blog/[slug].ts import { GetStaticProps , GetStaticPaths } from 'next' ;
import { getDataHooksProps } from 'next-data-hooks' ;
import BlogPost from 'routes/blog/components/blog-post' ;
export const getStaticPaths : GetStaticPaths = { } ; /* ... */
export const getStaticProps : GetStaticProps = async ( context ) => {
const dataHooksProps = getDataHooksProps ( {
context ,
dataHooks : BlogPost . dataHooks ,
} ) ;
return { props : dataHooksProps } ;
} ;
// re-export your component. this file is just an entry point
export default BlogPost ;NOTA: Lo anterior es solo un ejemplo de cómo puede usar
next-data-hookspara organizar su proyecto. La conclusión principal es que puede reexportar los componentes de la página para cambiar la estructura ynext-data-hooksfuncionan bien con este patrón.
Cada gancho de datos expone un método getData que es simplemente la función en la que se transfiere createDataHook .
Esto se puede usar dentro de otros ganchos de datos para extraer los mismos datos:
import { createDataHook } from 'next-data-hooks' ;
const useHook = createDataHook ( 'DataHook' , async ( context ) => {
return ; // ...
} ) ;
export default useHook ; import useHook from './' ;
const useOtherHook = createDataHook ( 'Other' , async ( context ) => {
const data = await useHook . getData ( context ) ;
// use data to do something…
} ) ;Nota: Tenga en cuenta que este método vuelve a ejecutar la función.
Para paquetes más pequeños, Next.js elimina el código que solo está destinado a ejecutarse dentro de getStaticProps .
next-data-hooks hace lo mismo con un complemento Babel que prefija su definición de gancho de datos con typeof window !== 'undefined' ? <stub> : <real data hook> .
Esto funciona porque NEXT.js preevalúa la typeof window a 'object' en los navegadores. Esto hará que el ternario anterior siempre se evalúe con el <stub> en el navegador. Terser luego sacude la expresión de <real data hook> que lo elimina del paquete del navegador.
Si vio el error Create data hook was run in the browser. Entonces algo puede haber salido mal con la eliminación del código. Abra un problema.
Nota . Puede haber diferencias en la eliminación de código predeterminada de Next.js y la eliminación del código
next-data-hooks. Revise dos veces su paquete.