typescriptnext.js

`'searchParams' is possibly 'null'` error in Next.js `useSearchParams`, even without a `/pages` directory


Environment


Problem

I'm working on a Next.js project using the App Router (not the Pages Router). At some point, running next build started throwing the following TypeScript error:

Type error: 'searchParams' is possibly 'null'.

This error is triggered by the following code:

'use client';
import { useSearchParams } from 'next/navigation';
import { Suspense, useEffect } from 'react';

function Onboarding() {
    const searchParams = useSearchParams();
    const reason = searchParams.get('reason');

    useEffect(() => {
        if (reason) {
            // ...
        }
    }, [reason]);

    // ...
}

export default function OnBoardingWrapper() {
    return (
        <Suspense fallback={<div>Loading...</div>}>
            <Onboarding />
        </Suspense>
    );
}

This didn't happen before, and I'm not sure what change caused it to appear.


What I’ve Tried

I investigated the error message and found that it's caused by searchParams being potentially null. However, useSearchParams normally returns a ReadonlyURLSearchParams—not a union with null.

Then I found this note in the Next.js documentation:

If an application includes the /pages directory, useSearchParams will return ReadonlyURLSearchParams | null. The null value is for compatibility during migration since search params cannot be known during pre-rendering of a page that doesn't use getServerSideProps.

But my project does not include a /pages directory—I'm fully using the App Router. So it seems like null should not be a possible return type in my case.


Question

Why am I getting a 'searchParams' is possibly 'null' error if I'm not using the /pages directory?**


Solution

  • Use the defensive null check:

    const searchParams = useSearchParams();
    const reason = searchParams?.get('reason') ?? null;
    

    Then in your useEffect, add a check with if condiiton:

    useEffect(() => {
      if (reason) {
        // ...
      }
    }, [reason]);