algolia / instantsearch

āš”ļø Libraries for building performant and instant search and recommend experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/
MIT License
3.69k stars 515 forks source link

Filter is not working via URL when its on same page: Next.js App Routing #6077

Closed naseef0 closed 6 months ago

naseef0 commented 7 months ago

šŸ› Current behavior

Filtering doesn't work via URL when staying on the same page. I've added quick filters that contain filtered URLs. Clicking any of the filtered URLs doesn't apply the filter. However, if I refresh the page, I get the filtered results. i have used InfiniteHits component

eg:

<div
    style={{
      display: "flex",
      justifyContent: "center",
      marginBottom: "20px",
      marginTop: "20px",
    }}
  >
    <Link
      style={{ marginRight: "10px" }}
      href="/?instant_search%5BrefinementList%5D%5BhierarchicalCategories.lvl0%5D%5B0%5D=Appliances&&id=1"
    >
      <button>Appliances</button>
    </Link>
    <Link
      style={{ marginRight: "10px" }}
      href="/?instant_search%5BrefinementList%5D%5BhierarchicalCategories.lvl0%5D%5B0%5D=Audio&instant_search%5BrefinementList%5D%5Bbrand%5D%5B0%5D=Bose%C2%AE&instant_search%5BrefinementList%5D%5Bbrand%5D%5B1%5D=JBL&instant_search%5BrefinementList%5D%5Brating%5D%5B0%5D=2"
    >
      <button>Audio</button>
    </Link>
    <Link
      style={{ marginRight: "10px" }}
      href="/?instant_search%5BrefinementList%5D%5BhierarchicalCategories.lvl0%5D%5B0%5D=Household%20Essentials&instant_search%5BrefinementList%5D%5BhierarchicalCategories.lvl0%5D%5B1%5D=Cameras%20%26%20Camcorders&instant_search%5BrefinementList%5D%5Bbrand%5D%5B0%5D=Nikon&instant_search%5BrefinementList%5D%5Bcategories%5D%5B0%5D=Short-Range%20Zoom%20Lenses"
    >
      <button>Cameras & Camcorders & Household Essentials</button>
    </Link>
  </div>
  <InstantSearchNext
    searchClient={client}
    indexName="instant_search"
    routing
  >
    <Configure hitsPerPage={1114} />

    <div className="Container">
      <div>
        <DynamicWidgets fallbackComponent={FallbackComponent} />
      </div>
      <div>
        {/* <SearchBox /> */}
        <InfiniteHits hitComponent={Hit} cache={sessionStorageCache} />
      </div>
    </div>
</InstantSearchNext>

šŸ” Steps to reproduce

  1. Go to browser.
  2. Click any of Quick filter shown above
  3. Nothing happens
  4. Refresh the page, you'll get result

Live reproduction

https://codesandbox.io/p/devbox/friendly-boyd-y42v3c?file=%2Fapp%2FSearch.tsx%3A58%2C1-72%2C31

šŸ’­ Expected behavior

If i click any of Quick filters i should get filtered results without refreshing the page

Package version

"algoliasearch": "4.22.1", "instantsearch.css": "8.1.0", "next": "13.5.1", "react": "18.2.0", "react-dom": "18.2.0", "react-instantsearch": "7.6.0", "react-instantsearch-nextjs": "0.1.13"

Operating system

Ubuntu 22.04.4 LTS

Browser

Firefox 123.0 (64-bit)

Code of Conduct

naseef0 commented 7 months ago

Anyone any update on this?

an00pss commented 7 months ago

I am also facing the same issue. Is there any fix for this?

aymeric-giraudet commented 7 months ago

Hey @naseef0,

Thanks for the feedback !

Unfortunately the app router for Next.js does not have events like the router for pages had.

There are some other changes that we need to do for routing, I'll take that in mind as well. I suppose we'll have to react to external changes with useParams.

In the meantime you could either call refine from useMenu instead of relying on Link, or maybe key the <InstantSearchNext> component with the URL. Or you can check the routing's prop arguments in which you may customize behavior.

naseef0 commented 7 months ago

@aymeric-giraudet Thanks, I'll try some workaround for this.

naseef0 commented 6 months ago

@aymeric-giraudet As of now, I have completely removed Algolia components and have instead utilised the algoliasearch client. Additionally, I have implemented a custom context to manage results and filters. Also i have used package nuqs for routing

aymeric-giraudet commented 6 months ago

Hi @naseef0,

The feature is in PR #6107 and should be in the next minor.

This workaround would have worked though :

export default function Search() {
  const searchParams = useSearchParams();
  const onUpdateRef = useRef<() => void>();
  useEffect(() => {
    if (onUpdateRef.current) {
      onUpdateRef.current();
    }
  }, [searchParams]);

  return (
    <InstantSearchNext
      searchClient={client}
      indexName="instant_search"
      routing={{
        router: {
          start(onUpdate) {
            onUpdateRef.current = onUpdate;
          },
        },
      }}
    >
    {/* Widgets */}
    </InstantSearchNext>
  );
}
naseef0 commented 6 months ago

Hi @naseef0,

The feature is in PR #6107 and should be in the next minor.

This workaround would have worked though :

export default function Search() {
  const searchParams = useSearchParams();
  const onUpdateRef = useRef<() => void>();
  useEffect(() => {
    if (onUpdateRef.current) {
      onUpdateRef.current();
    }
  }, [searchParams]);

  return (
    <InstantSearchNext
      searchClient={client}
      indexName="instant_search"
      routing={{
        router: {
          start(onUpdate) {
            onUpdateRef.current = onUpdate;
          },
        },
      }}
    >
    {/* Widgets */}
    </InstantSearchNext>
  );
}

Thanks @aymeric-giraudet, This works fine in codesandbox. Will wait for the next release.

RobinGiel commented 5 months ago

Although this was good for this use case when the URL need to be updated, but this is causing issues with Intercepting routes, where the Intercepted route is a URL opening a modal. Could there be a flag where we can optionally use this fix for the URLs?