tatethurston / nextjs-routes

Type safe routing for Next.js
MIT License
557 stars 21 forks source link

Typing next/navigation #105

Closed litewarp closed 1 year ago

litewarp commented 1 year ago

Apologies for multiple issues this week. Trying to type all the things with the new next13.

I notice that useRouter is typed only from the next/link import and not the new next/navigation module, and I was wondering if it will be supported in the future.

Thanks for the great package!

tatethurston commented 1 year ago

@litewarp No apologies necessary, I appreciate you taking the time to open issues. It’s easy to encounter a rough edge in a library and move on without giving any feedback.

Thank you for pointing that out, I can certainly look into adding support for next/navigation in the next few days.

tatethurston commented 1 year ago

I did some investigation here and the issue is Next.js: next/navigation when using the app directory has different runtime behavior than the pages directory.

When applications use the app directory, Link and useRouter -- only accept string arguments and no longer accept the UrlObject form that is available to applications using the pages directory.

I left a feedback request to accept the UrlObject form that is already supported by applications using the pages directory. Anyone interested in this can like the request here: https://github.com/vercel/next.js/discussions/41745#discussioncomment-4239793.

Example

Given a route /[store] from /app/stores/[store]/page.tsx:

// this will be`/stores/foo` when on `/stores/foo` _not_ `/stores/[store]` like for the pages directory router.
const pathname = usePathname();
const search = useSearchParams();
// this will be undefined when on `/stores/foo`, useSearchParams only returns search parameters, not dynamic segments
search.get('store');
tatethurston commented 1 year ago

A workaround is using route from nextjs-routes: https://github.com/tatethurston/nextjs-routes#what-if-i-need-a-runtime. Eg:

import { useRouter } from 'next/navigation';

useRouter.push(route({ pathname: "/foos/[foo]", query: { foo: "bar" } }));
tatethurston commented 1 year ago

Closing because this reflects the API that the nextjs team chose for the new app directory. If you would like to see this implemented, you can voice that here. I'm happy to revisit this if next/navigation becomes type-able beyond string

tatethurston commented 1 year ago

NextJS now supports this via an experimental configuration option: https://beta.nextjs.org/docs/configuring/typescript#statically-typed-links. Note: this only applies to app directory routes -- there is not route type generation for pages directory.

tatethurston commented 1 year ago

If there is sufficient interest in porting this functionality to nextjs-routes I'll look into it, but my current recommendation is that folks use next's builtin capability. Note: this only applies to app directory routes -- there is not route type generation for pages directory.

tran-simon commented 1 year ago

would be great for those who cant migrate to next 13

tatethurston commented 1 year ago

@tran-simon next/navigation comes from next13, could you explain your use case?

tran-simon commented 1 year ago

I'm on next12, I would like a way to type search parameters.

tatethurston commented 1 year ago

@tran-simon can you provide a code example?

tran-simon commented 1 year ago

For path www.myapp.com/organization/myorg?user=user

  const { query, push } = useRouter();

  const {user} = query

  // ...

  push({
    query: {
      user: 'test'
    }
  })

It would be great to have user strongly typed. That way, if in the future I rename user to something else typescript will complain if I forget to rename it in some places

tatethurston commented 1 year ago

@tran-simon did you mean to post on https://github.com/tatethurston/nextjs-routes/issues/39 instead?

This issue is specific to two new exports in next 13