-
Notifications
You must be signed in to change notification settings - Fork 531
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
Hits widget transformItems is called twice, receives already-transformed items #4819
Comments
Hi, thanks for reaching out. @algolia/instantsearch-for-websites I think a lot of users expect transformItems to apply only to the widget/connector they were defined on, so I'm wondering is we can make an exception on |
Ah, apologies, I did have a look through the issues, but couldn't find anything that seemed to match. For my use-case the doubling up of the transformation is the bigger issue. If it turns out it's necessary for the transformer to be called twice, would it be feasible for it to be passed the original, un-transformed hits array in both instances? |
Yes that would be a sensible behaviour, I'd need some time to look at the implications this change would have.
// instead of
const Hits = instantsearch.connectors.hits({
contrainer: "#hits",
transformItems: hits => myTransform(hits)
})
// do this
const Hits = instantsearch.connectors.connectHits((renderOptions, isFirstRender) => {
const { hits } = renderOptions;
const _hits = myTransform(hits);
document.querySelector('#hits').innerHTML = `
<ul>
${hits
.map(
item =>
`<li>
${instantsearch.highlight({ attribute: 'name', hit: item })}
</li>`
)
.join('')}
</ul>
`;
}); see our docs for more examples: https://www.algolia.com/doc/api-reference/widgets/hits/js/#connector-param-render-hits |
Yes, it would be interesting to hear why there's a problem if your transformItems gets called multiple times. Which transformation do you do in it? |
Thanks, I'll take a look.
In our case it's a product object that gets transformed into a more view-friendly format, including image path concatenation and a price conversion into the local currency. Here's a simplfied example: function transformItem(product) {
return {
name: product.name,
image: THUMBNAIL_PATH + product.image,
price: toLocalCurrency(product.basePrice.gross), // e.g. 12.5 > "€13,73"
};
} When the second transformation call is made, it's passed the already-transformed items and raises an error because the |
I see how that's problematic, for the time being I can only think of in transformItems adding new keys you plan to display instead of actually changing existing values. Not sure yet how, but I think we probably should avoid this as it could be considered a bug. I think it happens because we set the result of transformItems to |
No worries - I've got a few different workarounds that I can try, now that I have a better understanding of what's going on. Thanks for all your help! |
Since we introduced getWidgetRenderState, transformItems gets called two times. On its own this isn't problematic, however if the transformItems "mutates" a key, it will receive next the "mutated" hits instead of the ones that come from the results One thing which is debatable about this PR is which parts should be saved to `results.hits`. I opted for just the escaped hits, but i wonder if there's any use cases for considering the query id and position as part of the hits directly. However, I feel like if we want this behaviour, it shouldn't be hits and infiniteHits mutating results, but rather something global that gets called right after the results get returned. In fact, I also think it makes more sense to escape hits there than in hits. I don't think removing the escapeHTML option is possible here without breaking change though, so if we want to do that, we should mark it as a possibility for a major in this PR FX-11 fixes #4819
* fix(infinite/hits): stop saving the transformed results in cache Since we introduced getWidgetRenderState, transformItems gets called two times. On its own this isn't problematic, however if the transformItems "mutates" a key, it will receive next the "mutated" hits instead of the ones that come from the results One thing which is debatable about this PR is which parts should be saved to `results.hits`. I opted for just the escaped hits, but i wonder if there's any use cases for considering the query id and position as part of the hits directly. However, I feel like if we want this behaviour, it shouldn't be hits and infiniteHits mutating results, but rather something global that gets called right after the results get returned. In fact, I also think it makes more sense to escape hits there than in hits. I don't think removing the escapeHTML option is possible here without breaking change though, so if we want to do that, we should mark it as a possibility for a major in this PR FX-11 fixes #4819 * simplify answers too
🐛 Bug description
It appears that the transformItems function of the hits widget is being called twice for a single search invocation, and is receiving the already-transformed items on the second run.
🔍 Bug reproduction
Steps to reproduce the behavior:
transformItems
callback to the hits widget that returns transformed items.console.log
notification somewhere inside the transformation function.Live reproduction:
https://codesandbox.io/s/fervent-frost-bbzb5?file=/src/app.js
https://codesandbox.io/s/stupefied-frog-c2krg?file=/src/instantsearch.ts
Including two examples here, one based on
create-instantsearch-app
and another based on the instantsearch sandbox from the main documentation. The latter already included atransformItems
call, so required fewer additions on my part.💭 Expected behavior
transformItems
is called only once for a single search invocation, and is never passed already-transformed items.Environment
Additional context
I've run into this bug while upgrading from an older 4.3.1 install to the latest 4.25.2 release. However, experimenting via codesandbox.io reveals that the bug was likely introduced in the 4.9 branch, as 4.9.2 is the earliest release I tested that allowed me to replicate it.
It particularly affects us because our transformed items cannot be safely transformed a second time, leading to an unexpected runtime error rather than it silently continuing.
Possibly related to this issue in the vue-instantsearch repo?
The text was updated successfully, but these errors were encountered: