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

Statemapping not working with instantsearch.js 4.61.0 #5954

Closed
1 task done
chrissshh opened this issue Dec 5, 2023 · 5 comments · Fixed by #5956
Closed
1 task done

Statemapping not working with instantsearch.js 4.61.0 #5954

chrissshh opened this issue Dec 5, 2023 · 5 comments · Fixed by #5956
Labels
Library: InstantSearch.js Issues in instantsearch.js Type: Bug

Comments

@chrissshh
Copy link

🐛 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
@chrissshh chrissshh added the triage Issues to be categorized by the team label Dec 5, 2023
@Haroenv
Copy link
Contributor

Haroenv commented Dec 6, 2023

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?

@Haroenv Haroenv added Library: React InstantSearch ≥ 7 Issues in any of the react-instantsearch@7 packages (formerly named react-instantsearch-hooks) and removed triage Issues to be categorized by the team labels Dec 6, 2023
@chrissshh
Copy link
Author

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.

@Haroenv
Copy link
Contributor

Haroenv commented Dec 6, 2023

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.

@Haroenv Haroenv changed the title Statemapping not working with react-instantsearch-nextjs 0.1.5 Statemapping not working with instantsearch.js 4.61.0 Dec 6, 2023
@Haroenv Haroenv added Library: InstantSearch.js Issues in instantsearch.js Type: Bug and removed Library: React InstantSearch ≥ 7 Issues in any of the react-instantsearch@7 packages (formerly named react-instantsearch-hooks) labels Dec 6, 2023
@chrissshh
Copy link
Author

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.

@Haroenv
Copy link
Contributor

Haroenv commented Dec 7, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Library: InstantSearch.js Issues in instantsearch.js Type: Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants