Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating url with hash #498

Closed
JoakimGit opened this issue Feb 12, 2024 · 10 comments
Closed

Updating url with hash #498

JoakimGit opened this issue Feb 12, 2024 · 10 comments
Labels
bug Something isn't working next.js Issue is related to Next.js internals rather than this library

Comments

@JoakimGit
Copy link

JoakimGit commented Feb 12, 2024

Context

What's your version of nuqs?

1.16.1

Next.js information (obtained by running next info):

Relevant Packages:
  next: 14.1.0
  react: ^18
  react-dom: ^18
  typescript: ^5
Next.js Config:
  output: N/A

Are you using:

  • ✅ The app router
  • ❌ The pages router
  • ❌ The basePath option in your Next.js config
  • ❌ The experimental windowHistorySupport flag in your Next.js config

Description

Updating the query param with the setter returned from useQueryState causes an error if there's a hash fragment in the url.

Reproduction

codesandbox

  1. Click on the link 'Go section' which jumps to a section of content, adding a hash to the url
  2. Type in the input field some query text
  3. See error in console: TypeError: Cannot read properties of null (reading '__PRIVATE_NEXTJS_INTERNALS_TREE')

I was initially following the way as described in the NextJS docs Using the native History API, but I was getting this error when calling window.history.pushState.

const searchParams = useSearchParams();
const pathname = usePathname();

const searchChange = (term: string) => {
    const params = new URLSearchParams(searchParams)
    if (term) {
      params.set('query', term);
    } else {
      params.delete('query');
    }
    window.history.pushState(null, "", `${pathname}?${params.toString()}`);
  }

<input onChange={(e) => searchChange(e.target.value) />

This led me to trying this package, but I'm getting the same error.

@JoakimGit JoakimGit added the bug Something isn't working label Feb 12, 2024
@franky47
Copy link
Member

I see no link nor input field in your linked codesandbox, only a stock create-next-app template.

@JoakimGit
Copy link
Author

JoakimGit commented Feb 12, 2024

I don't know how to share the codesandbox. I am copying the link I get from "copy link" in the share dialog, but you're right, it's just the empty template when I then go to the link.

It's simply the basic nextjs template with nuqs installed and page.tsx looks like this:

import SearchBar from "./_components/searchbar";

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <SearchBar />

      <a className="my-8" href="#mysection">
        Go to section
      </a>

      <div id="mysection">
        Lorem ipsum dolor sit amet consectetur adipisicing elit.
      </div>
    </main>
  );
}

and _components/searchbar looks like this:

"use client";

import { useQueryState } from "nuqs";

const SearchBar = () => {
  const [query, setQuery] = useQueryState("query");
  return (
    <input
      className="py-2 px-4"
      placeholder="Search.."
      type="text"
      onChange={(e) => setQuery(e.target.value)}
      defaultValue={query ?? ""}
    />
  );
};

export default SearchBar;

@franky47
Copy link
Member

I can reproduce the issue, with the following notes:

  • replacing the <a> with a <Link> solves the issue. Not a valid solution, but a step towards understanding the problem better.
  • doing a page reload between applying the hash and applying search params also solved the problem

Coupled with the fact that you encountered a similar issue with updating search params via the history method (which nuqs does under the hood), it looks like the issue is in Next.js' router, which is not aware of the hash application via an anchor tag, and fails subsequent shallow history updates.

I'll dive deeper into this today, and see if I can open a PR to fix this in Next.js.

@JoakimGit
Copy link
Author

Thank you for looking into this so fast. I believe using <Link> instead of <a> is possible for my use case, but it would be nice to see this fixed. Good luck on the PR.

@franky47
Copy link
Member

franky47 commented Feb 13, 2024

A "fix" for this was started in vercel/next.js#61822, but there are still some major issues with it.

As of next@14.1.1-canary.51, search params and hash are dropped out of the URL, and even with an easy fix, it still results in a full-page reload when updating the search params, which is terrible UX for nuqs. This is going to require close collaboration with the Next.js team to iterate on a fix that can work with anchor tags.

@franky47
Copy link
Member

Another PR by the Next.js team should fix this properly: vercel/next.js#62098

I'll wait until it gets merged into a canary release to run the test suite in #500. Unfortunately that means this bug is here to stay in next@14.1.0 (and all previous versions with the WHS flag), so it looks like nuqs@^2 will have a hard peer-requirement on next@^14.1.1 (or whatever they decide to call the next GA).

@franky47
Copy link
Member

Fixed in next@14.1.1-canary.55, so the next GA should be good.

@kuiber
Copy link

kuiber commented Feb 16, 2024

Fixed in next@14.1.1-canary.55, so the next GA should be good.

I've tested this nextjs release and it has fixed this issue for me.

@franky47
Copy link
Member

Next.js 14.1.1 was released, but with only a very partial subset of PRs since the previous version, and which doesn't include this fix..

Going to have to wait for the next one I'm afraid (I guess I know why they called it Next now).

@franky47
Copy link
Member

Fixed in Next.js 14.1.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working next.js Issue is related to Next.js internals rather than this library
Projects
None yet
Development

No branches or pull requests

3 participants