Skip to main content

@nimpl/getters

(Former next-impl-getters )

Implementation of server getters in React Server Components without switching to SSR.

Before using the library, read the Possible Issues

Installation 

Using npm:

npm i @nimpl/getters

Current Getters 

Contexts, due to the release of react v19, have been moved to a separate package - @nimpl/context

Stability 

All getters are covered with tests. Tests are run on every release and every 6 hours on the latest Canary version of Next.js.

In this way, you can be sure not only of the stability of the code, but also that if there is a breaking change in Next.js, this will immediately become known. Even before the release of a stable version of Next.js.

get-pathname 

Uses next.js functionality

Retrieves pathname for the currently rendered page in React Server Component. Works the same as usePathname , but in a React server component.

The getter almost fully utilizes Next.js functionality

import { getPathname } from '@nimpl/getters/get-pathname'

export default function Component() {
const pathname = getPathname()

return (
// ...
)
}

get-params 

Uses next.js functionality

Retrieves dynamic parameters for the current page. Works the same as useParams , but in a React server component.

For example, for a page at the directory /[locale]/blog/[slug] and pathname /en-de/blog/example - the getter will return { locale: 'en-de', slug: 'example' }

import { getParams } from '@nimpl/getters/get-params'

export default function Component() {
const params = getParams()

return (
// ...
)
}

Options

You can pass params object as arguments to getParams.

ignoreDifferenceError - this option disables difference errors, and in such situations, the function will simply return null.

pagePaths - custom page paths for parsing the current pathname (e.g., ["/specific/[locale]/[...subpaths]/page", "/[locale]/base/[...subpaths]/page"]).

const params = getParams({
ignoreDifferenceError: true,
pagePaths: ["/specific/[locale]/[...subpaths]/page", "/[locale]/base/[...subpaths]/page"],
});
// "/specific/de/unknown-page" -> { locale: "de", subpaths: ["unknown-page"] }
// "/it/base/unknown-page" -> { locale: "it", subpaths: ["unknown-page"] }
// "/it/invalid/unknown-page" -> null

get-page-config 

Uses next.js functionality

Gets the next.js page configuration for the currently rendered page in React Server Component.

Supported configuration data

basePath - project base path (sub-path of a domain). Read more in next.js docs 

dynamic - next.js dynamic behavior option. Read more in next.js docs 

pagePath - path to the page in the folder structure (f.e. /[locale]/blog/[slug])

revalidate - revalidation time for rendered page. Read more in next.js docs 

import { getPageConfig } from '@nimpl/getters/get-page-config'
// ...

export default function Component() {
const { basePath, dynamic, pagePath, revalidate } = getPageConfig()

// getters are not hooks, so you can use them inside conditions
if (dynamic === 'force-dynamic') {
const searchParams = getSearchParams()
// ...
}

return (
// ...
)
}

get-search-params 

Retrieves search params for the currently rendered page in React Server Component. Works the same as useSearchParams , but in a React server component.

Getter was deprecated in version 1.2.0 because in some cases next.js can strip query parameters from the stored URL.

Possible implementation

This functionality makes no sense without dynamic mode, so you can use headers to implement it

1. Add URL header in middleware

middleware.ts
import { NextResponse } from 'next/server';

export function middleware(request: Request) {
const next = NextResponse.next();
next.headers.set('x-url', request.url);

return next;
}

2. Use new header

import { headers } from 'next/headers';
import { getPageConfig } from '@nimpl/getters/get-page-config';

export default function Component() {
const { dynamic } = getPageConfig();

if (dynamic === 'force-dynamic') {
const url = headers().get('x-url') || '';
const { searchParams } = new URL(url, 'http://n');
}
}

Previous solution

import { getSearchParams } from '@nimpl/getters/get-search-params'

export default function Component() {
const searchParams = getSearchParams()

const source = searchParams.get('source')

return (
// ...
)
}

Because the getter works on every request, the dynamic page parameter must be set to dynamic (not static) for it to work.

If the page has the dynamic='force-static' or dynamic='error' option specified, the getter will throw an error. If this option is not specified, it will output a warning. It is recommended to specify force-dynamic:

/app/**/page.tsx
export const dynamic = 'force-dynamic'

If you are sure you want to ignore the logic with checking the dynamic option - pass { ignoreDynamicOptionErrors: true } as the first argument in the getter.

const searchParams = getSearchParams({ ignoreDynamicOptionErrors: true })

What's next? 

Why getters instead of extending existing hooks?

I'm not very fond of the idea of extending hooks - on the server, it won't be a hook no matter how you look at it. These are specifically getters. Moreover, a client-side hook can be synchronous, while a server-side getter for the same task can be asynchronous, making it a more versatile format.

Possible Issues 

As a potential risk of a server-side solution, the problem of Layouts is mentioned, that they do not rebuild, which is inherent in the app router foundation. I don't see any reason to change this logic.

The most reliable approach, in my opinion, is to output messages to the console or even throw an error when this function is used in Layout or Error without the necessary conditions.

Since at the moment it is impossible to determine in which route the component is rendered - there are no automatic errors. However, it is strongly discouraged to use this feature in layouts.

Development 

Read about working on the package and making changes on the contribution page

Additional 

This package came as an attempt to implement a working get-pathname solution while waiting for a PR  merge to add get-pathname to next.js. However, it proved to be an independent solution.

Please consider giving a star if you like it, it shows that the package is useful and helps continue work on this and other packages.

Create issues with wishes, ideas, difficulties, etc. All of them will definitely be considered and thought over.

Previous
Introduction
Next
Internationalization
Return to navigation