Skip to content

Commit

Permalink
fix(rendering): ensure resilience against "null" results
Browse files Browse the repository at this point in the history
In some cases `results` in `render` can be null:
- no index name passed
- stalled render

In the vast majority of cases we already handled `results` being `null` or `undefined` just in case, but now i've changed the type to ensure we always catch this problem

This issue doesn't have a reproduction, but i believe it now guards for all possible cases of "no results", so:
fixes #6441

[CR-7353]
  • Loading branch information
Haroenv committed Nov 19, 2024
1 parent c098cb4 commit 094ae4f
Show file tree
Hide file tree
Showing 9 changed files with 27 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,21 +183,23 @@ search.addWidgets([
const indices = scopedResults.map((scopedResult) => {
// We need to escape the hits because highlighting
// exposes HTML tags to the end-user.
scopedResult.results.hits = escapeHTML
? escapeHits(scopedResult.results.hits)
: scopedResult.results.hits;
if (scopedResult.results) {
scopedResult.results.hits = escapeHTML
? escapeHits(scopedResult.results.hits)
: scopedResult.results.hits;
}

const sendEvent = createSendEventForHits({
instantSearchInstance,
getIndex: () => scopedResult.results.index,
getIndex: () => scopedResult.results?.index || '',
widgetType: this.$$type,
});

return {
indexId: scopedResult.indexId,
indexName: scopedResult.results.index,
hits: scopedResult.results.hits,
results: scopedResult.results,
indexName: scopedResult.results?.index || '',
hits: scopedResult.results?.hits || [],
results: scopedResult.results || ({} as unknown as SearchResults),
sendEvent,
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function getAttributesToClear({
includedAttributes: string[];
excludedAttributes: string[];
transformItems: TransformItems<string>;
results: SearchResults | undefined;
results: SearchResults | undefined | null;
}): AttributesToClear {
const includesQuery =
includedAttributes.indexOf('query') !== -1 ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ const connectCurrentRefinements: CurrentRefinementsConnector =
if (!results) {
return transformItems(
getRefinementsItems({
results: {},
results: null,
helper,
indexId: helper.state.index,
includedAttributes,
Expand Down Expand Up @@ -282,7 +282,7 @@ function getRefinementsItems({
includedAttributes,
excludedAttributes,
}: {
results: SearchResults | Record<string, never>;
results: SearchResults | null;
helper: AlgoliaSearchHelper;
indexId: string;
includedAttributes: CurrentRefinementsConnectorParams['includedAttributes'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export type InfiniteHitsRenderState<
/**
* The response from the Algolia API.
*/
results?: SearchResults<Hit<THit>>;
results?: SearchResults<Hit<THit>> | null;

/**
* The banner to display above the hits.
Expand Down Expand Up @@ -435,7 +435,7 @@ export default (function connectInfiniteHits<
sendEvent,
bindEvent,
banner,
results,
results: results || undefined,
showPrevious,
showMore,
isFirstPage,
Expand Down
3 changes: 2 additions & 1 deletion packages/instantsearch.js/src/lib/utils/getRefinements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,11 @@ function getRefinement(
}

export function getRefinements(
results: SearchResults | Record<string, never>,
_results: SearchResults | Record<string, never> | null,
state: SearchParameters,
includesQuery: boolean = false
): Refinement[] {
const results = _results || {};
const refinements: Refinement[] = [];
const {
facetsRefinements = {},
Expand Down
2 changes: 1 addition & 1 deletion packages/instantsearch.js/src/lib/utils/render-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function createRenderArgs(
parent: IndexWidget,
widget: IndexWidget | Widget
) {
const results = parent.getResultsForWidget(widget)!;
const results = parent.getResultsForWidget(widget);
const helper = parent.getHelper()!;

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,10 @@ export function createInsightsMiddleware<
instantSearchInstance.mainHelper!.derivedHelpers[0].on(
'result',
({ results }) => {
if (!results.queryID || results.queryID !== lastQueryId) {
if (
results &&
(!results.queryID || results.queryID !== lastQueryId)
) {
lastQueryId = results.queryID;
viewedObjectIDs.clear();
}
Expand Down
6 changes: 3 additions & 3 deletions packages/instantsearch.js/src/types/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {

export type ScopedResult = {
indexId: string;
results: SearchResults;
results: SearchResults | null;
helper: Helper;
};

Expand Down Expand Up @@ -45,7 +45,7 @@ export type InitOptions = SharedRenderOptions & {
export type ShouldRenderOptions = { instantSearchInstance: InstantSearch };

export type RenderOptions = SharedRenderOptions & {
results: SearchResults;
results: SearchResults | null;
};

export type DisposeOptions = {
Expand Down Expand Up @@ -339,7 +339,7 @@ export type Widget<
export type { IndexWidget } from '../widgets';

export type TransformItemsMetadata = {
results?: SearchResults;
results: SearchResults | undefined | null;
};

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/instantsearch.js/src/widgets/analytics/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ For the migration, visit https://www.algolia.com/doc/guides/building-search-ui/u
},

render({ results, state }) {
if (!results) {
return;
}
if (isInitialSearch === true) {
isInitialSearch = false;

Expand Down

0 comments on commit 094ae4f

Please sign in to comment.