next.js icon indicating copy to clipboard operation
next.js copied to clipboard

`next/compat/router`

Open wyattjoh opened this issue 3 years ago • 0 comments

After speaking with @timneutkens, this PR provides a smoother experience to users trying to migrate over to app without affecting users in pages.

This PR adds a new export available from next/compat/router that exposes a useRouter() hook that can be used in both app/ and pages/. It differs from next/router in that it does not throw an error when the pages router is not mounted, and instead has a return type of NextRouter | null. This allows developers to convert components to support running in both app/ and pages/ as they are transitioning over to app/.

A component that before looked like this:

import { useRouter } from 'next/router';

const MyComponent = () => {
  const { isReady, query } = useRouter();
  // ...
};

Will error when converted over to next/compat/router, as null cannot be destructured. Instead, developers will be able to take advantage of new hooks:

import { useEffect } from 'react';
import { useRouter } from 'next/compat/router';
import { useSearchParams } from 'next/navigation';

const MyComponent = () => {
  const router = useRouter() // may be null or a NextRouter instance
  const searchParams = useSearchParams()

  useEffect(() => {
    if (router && !router.isReady) {
      return
    }

    // In `app/`, searchParams will be ready immediately with the values, in
    // `pages/` it will be available after the router is ready.
    const search = searchParams.get('search')
    // ...
  }, [router, searchParams])

  // ...
}

This component will now work in both pages/ and app/. When the component is no longer used in pages/, you can remove the references to the compat router:

import { useSearchParams } from 'next/navigation';

const MyComponent = () => {
  const searchParams = useSearchParams()

  // As this component is only used in `app/`, the compat router can be removed.
  const search = searchParams.get('search')

  // ...
}

Note that as of Next.js 13, calling useRouter from next/router will throw an error when not mounted. This now includes an error page that can be used to assist developers.

We hope to introduce a codemod that can convert instances of your useRouter from next/router to next/compat/router in the future.

wyattjoh avatar Nov 04 '22 19:11 wyattjoh