algolia / instantsearch

⚑️ Libraries for building performant and instant search experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.

Home Page:https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Statemapping not working with instantsearch.js 4.61.0

chrissshh opened this issue Β· comments

πŸ› Current behavior

I get an error saying that statemapping.stateToRoute is not a function when loading a page with react-instantsearch-nextjs. This didn't happen with the version I had previously to updating.

How can I fix this?

<InstantSearchNext
      indexName="products"
      searchClient={searchClient}
      routing={{
        stateMapping: {
          stateToRoute(uiState) {
            const indexUiState = uiState["products"];
            return {
              colors:
                indexUiState.refinementList &&
                indexUiState.refinementList["color_name"] &&
                indexUiState.refinementList["color_name"].join("-"),
              sizes:
                indexUiState.refinementList &&
                indexUiState.refinementList["sizes"] &&
                indexUiState.refinementList["sizes"].join("-"),
              price: indexUiState.numericMenu?.prices,
              sort: indexUiState.sortBy,
              q: indexUiState.query,
            };
          },
          routeToState(routeState) {
            return {
              ["products"]: {
                refinementList: {
                  color_name: routeState.colors && routeState.colors.split("-"),
                  sizes: routeState.sizes && routeState.sizes.split("-"),
               
                },
                sortBy: routeState.sort,
                query: routeState.q,
                numericMenu: {
                  prices: routeState.price,
                },
              },
            };
          },
        },
      }}
>

πŸ” Steps to reproduce

Add statemapping code above to an instance of react-instantsearch-nextjs.

Live reproduction

codesandbox.io

πŸ’­ Expected behavior

Statemapping to work as in previous versions where I can create a custom url from the current uiState.

Package version

react-instantsearch-nextjs 0.1.5

Operating system

No response

Browser

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Which version did you have previously? the only change between 0.1.4 and 0.1.5 is marking it compatible with next 14. Do you have a reproducible example of this issue?

It seems to be giving me this error:

node_modules\instantsearch.js\es\connectors\refinement-list\connectRefinementList.js (286:41) @ eval
 β¨― TypeError: Cannot read properties of undefined (reading 'length')

Referencing this component:

function XRefinementList({
  attribute,
}: {
  attribute: string;
}) {
  const { items, refine } = useRefinementList({
    attribute: attribute,
    sortBy: ["count:desc", "name:asc"],
  });
  return (
    <div>
      {items.map((item) => (
        <div key={item.label} >
          <button
            type="button"
            onClick={() => {
              refine(item.value);
            }}
          >
            {item.label}
            <span >
              {item.count}
            </span>
          </button>
        </div>
      ))}
    </div>
  );
}

with these routing settings

  routing={{
        stateMapping: {
          stateToRoute(uiState) {
            const indexUiState = uiState["products"];
            return {
              colors:
                indexUiState.refinementList &&
                indexUiState.refinementList["color_name"] &&
                indexUiState.refinementList["color_name"].join("-"),
              sizes:
                indexUiState.refinementList &&
                indexUiState.refinementList["sizes"] &&
                indexUiState.refinementList["sizes"].join("-"),
              seasons:
                indexUiState.refinementList &&
                indexUiState.refinementList["seasons"] &&
                indexUiState.refinementList["seasons"].join("-"),
              brands:
                indexUiState.refinementList &&
                indexUiState.refinementList["brand_name"] &&
                indexUiState.refinementList["brand_name"].join("-"),
              occasions:
                indexUiState.refinementList &&
                indexUiState.refinementList["occasions"] &&
                indexUiState.refinementList["occasions"].join("-"),
              price:
                indexUiState.numericMenu && indexUiState.numericMenu.prices
                  ? indexUiState.numericMenu.prices
                  : undefined,
              sort: indexUiState.sortBy,
              q: indexUiState.query,
            };
          },
          routeToState(routeState) {
            return {
              products: {
                refinementList: {
                  color_name: routeState.colors && routeState.colors.split("-"),
                  sizes: routeState.sizes && routeState.sizes.split("-"),
                  brand_name: routeState.brands && routeState.brands.split("-"),
                  occasions:
                    routeState.occasions && routeState.occasions.split("-"),
                  seasons: routeState.seasons && routeState.seasons.split("-"),
                },
                sortBy: routeState.sort,
                query: routeState.q,
                numericMenu: {
                  prices: routeState.price,
                },
              },
            };
          },
        },
      }}

Changing routing to True makes everything work fine again but with long and complex Url parameters. What could be causing this issue and is there a fix I can try? I've already tried adding a static attribute and removing any props but that didn't solve it.

This error happens because of:

const connectorUiState = Object.keys(refinementList).reduce(
(acc, key) => ({
...acc,
...(refinementList[key].length > 0 ? { [key]: refinementList[key] } : {}),
}),
{}
);

This code was introduced (#5912) in the latest version of InstantSearch.js, so if you revert to the previous (4.60.0 instead of 4.61.0) it should at least not error.

It seems like you're not always returning arrays from the values of refinementList, maybe the falsy value somehow is wrong? Do you mind debugging and finding what the value of indexUiState is before that function?

I wonder if it's related to the key existing but having value undefined? if you'd clarify what situation you have I could help more.

I don't see what the wrong value would be based just on looking at the code, but maybe could find it if you make a reproducible example.

It looks like "react-instantsearch" version 7.4.0 is causing these errors.

Everything is working fine now with this setup:
"react-instantsearch-nextjs": Latest version
"instantsearch.js": Latest version
"react-instantsearch": version 7.3.0 (downgraded from 7.4.0)

I've added a console.log() to get the uiState before stateMapping. RouteToState logged a value according to the parameters in the URL but stateToRoute didn't log anything with "react-instantsearch" version 7.4.0.

Thanks for your report, this is now fixed in #5956 and being released in #5957