# @gasket/nextjs Gasket integrations for Next.js apps. Provides several tools: **AppRouter** - [request]: Access a request-like object in server components - [withGasketData][withGasketData2]: HOC to inject Gasket Data into Root Layout **PageRouter** - [withGasketData]: HOC to inject Gasket Data into Document - [withGasketDataProvider]: HOC to provide React Context access to Gasket Data - [useGasketData]: Hook that enables access to Gasket Data - [withLocaleInitialProps]: HOC to add current locale with `getInitialProps` ## Installation ``` npm i @gasket/nextjs ``` ## App Router Functions to help integrate Gasket with Next.js App Router. ### request Get a normalized [GasketRequest] unique to the current request in server components. This uses the Next.js `cookies()` and `headers()` [dynamic functions]. **Signature** - `await request(params?: object): GasketRequest` **Props** - `[query]` - (object) Optional query object Many GasketActions are designed to be unique to requests. When using ServerComponents with Next.js, the incoming request object is not fully accessible. This function provides a way to get a normalized request-like object that can be used with GasketActions from ServerComponents. #### Example ```js import { request } from '@gasket/nextjs/request'; import gasket from '../gasket.mjs' export default async function MyPage(props) { const req = await request(); const something = await gasket.actions.getSomething(req); return
{ something.fancy }
; } ``` The `req` will be a [GasketRequest] with headers and cookies. If a query object is passed in, it will be added to the request object as well. For server components, dynamic routes params are available via props, and can be passed to the `request` function to make those path params available as the query. ```js import { request } from '@gasket/nextjs/request'; import gasket from '../gasket.mjs' export default async function MyDynamicRoutePage({ params }) { const req = request(params); const something = await gasket.actions.getSomething(req); return
{ something.fancy }
; } ``` #### App Router limitations The App Router does not expose a request object. `request()` assembles a request-like object from `next/headers`, which has two consequences for the [GasketRequest] you get back: - `method` is `undefined`. `next/headers` provides no method, and it is not defaulted to `GET` because a Server Action is a `POST` that re-renders server components within the same request. - `getOriginalRequest()` returns the assembled object, not a framework request. It is truthy but carries only headers, cookies, and query — so there is no `ip` on it. Guard the field you need, not the object: ```js import { getOriginalRequest } from '@gasket/request'; const ip = getOriginalRequest(req)?.ip; if (!ip) { // No client IP available in this environment } ``` ### Layout withGasketData Injects Gasket Data into Root Layout for use with the [@gasket/data] package. **Signature** - `withGasketData(gasket, options?)(Layout)` **Props** - `gasket` - (object) The Gasket instance - `[options]` - (object) Optional configuration - `index` - (number) Force the script to be inject at a certain child index of the body #### Example This is the simplest and most common setup: ```jsx // app/layout.js import { withGasketData } from '@gasket/nextjs/layout'; import gasket from '../gasket.js'; async function RootLayout({ children }) { return ( {children} ); } export default withGasketData(gasket)(RootLayout); ``` ## Page Router Functions to help integrate Gasket with Next.js Page Router. ### withGasketData Use this to extend your Next.js Document to automatically inject a script containing the `gasketData` for use with the [@gasket/data] package. **Signature** - `withGasketData(options)(Document)` **Props** - `[options]` - (object) Optional configuration - `index` - (number) Force the script to be inject at a certain child index of the body #### Example This is the simplest and most common setup: ```jsx // pages/_document.js import Document from 'next/document'; import { withGasketData } from '@gasket/nextjs/document'; import gasket from '../gasket.js'; export default withGasketData(gasket)(Document); ``` By default this will inject the script in the `` after the Next.js `
` component, but before ``. This also works for a [custom Document]. #### Example forced index However, there may be situations where you want to inject the `gasketData` script at a particular child index of the ``. To do so, you can set the `index` in the decorator options. ```jsx // pages/_document.js import Document, {Html, Head, Main, NextScript} from 'next/document' import { withGasketData } from '@gasket/nextjs/document'; import gasket from '../gasket.js'; class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx) return {...initialProps} } render() { return (
Some custom content
) } } export default withGasketData(gasket, {index: 2})(MyDocument); ``` In this example, the `gasketData` script will be injected after the custom `