Skip to content

Commit

Permalink
refactor(bindEvent): move listener inside components (#5528)
Browse files Browse the repository at this point in the history
* refactor(bindEvent): move listener inside components

This was needlessly abstracted with a HOC, not allowing us to use this same function inside onClick of an individual hit, which could help with deduplicating sendEvent + bindEvent

I didn't remove the `withInsightsListener` HOC, as it could (in theory) be used externally.

* remove unused data
  • Loading branch information
Haroenv authored Mar 8, 2023
1 parent bb4c356 commit b4e9504
Show file tree
Hide file tree
Showing 14 changed files with 1,476 additions and 1,209 deletions.
21 changes: 14 additions & 7 deletions packages/instantsearch.js/src/components/Hits/Hits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { cx } from '@algolia/ui-components-shared';
import { h } from 'preact';

import { createInsightsEventHandler } from '../../lib/insights/listener';
import { warning } from '../../lib/utils';
import Template from '../Template/Template';

import type { PreparedTemplateProps } from '../../lib/templating';
import type { BindEventForHits, SendEventForHits } from '../../lib/utils';
import type { ComponentCSSClasses, Hit } from '../../types';
import type { ComponentCSSClasses, Hit, InsightsClient } from '../../types';
import type { HitsCSSClasses, HitsTemplates } from '../../widgets/hits/hits';
import type { SearchResults } from 'algoliasearch-helper';

Expand All @@ -18,35 +19,43 @@ export type HitsComponentTemplates = Required<HitsTemplates>;
export type HitsProps = {
results: SearchResults;
hits: Hit[];
insights?: InsightsClient;
sendEvent: SendEventForHits;
bindEvent: BindEventForHits;
cssClasses: HitsComponentCSSClasses;
templateProps: PreparedTemplateProps<HitsComponentTemplates>;
};

const Hits = ({
export default function Hits({
results,
hits,
insights,
bindEvent,
sendEvent,
cssClasses,
templateProps,
}: HitsProps) => {
}: HitsProps) {
const handleInsightsClick = createInsightsEventHandler({
insights,
sendEvent,
});

if (results.hits.length === 0) {
return (
<Template
{...templateProps}
templateKey="empty"
rootProps={{
className: cx(cssClasses.root, cssClasses.emptyRoot),
onClick: handleInsightsClick,
}}
data={results}
/>
);
}

return (
<div className={cssClasses.root}>
<div className={cssClasses.root} onClick={handleInsightsClick}>
<ol className={cssClasses.list}>
{hits.map((hit, index) => (
<Template
Expand Down Expand Up @@ -77,6 +86,4 @@ const Hits = ({
</ol>
</div>
);
};

export default Hits;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
exports[`Hits markup should render <Hits /> 1`] = `
<div
className="root"
onClick={[Function]}
>
<ol
className="list"
Expand Down Expand Up @@ -32,6 +33,7 @@ exports[`Hits markup should render <Hits /> 1`] = `
exports[`Hits markup should render <Hits /> without highlight function 1`] = `
<div
className="root"
onClick={[Function]}
>
<ol
className="list"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import { cx } from '@algolia/ui-components-shared';
import { h } from 'preact';

import { createInsightsEventHandler } from '../../lib/insights/listener';
import { warning } from '../../lib/utils';
import Template from '../Template/Template';

import type { SendEventForHits, BindEventForHits } from '../../lib/utils';
import type { ComponentCSSClasses, Hit } from '../../types';
import type { ComponentCSSClasses, Hit, InsightsClient } from '../../types';
import type {
InfiniteHitsCSSClasses,
InfiniteHitsTemplates,
Expand All @@ -31,13 +32,15 @@ export type InfiniteHitsProps = {
};
isFirstPage: boolean;
isLastPage: boolean;
insights?: InsightsClient;
sendEvent: SendEventForHits;
bindEvent: BindEventForHits;
};

const InfiniteHits = ({
results,
hits,
insights,
bindEvent,
sendEvent,
hasShowPrevious,
Expand All @@ -48,21 +51,27 @@ const InfiniteHits = ({
cssClasses,
templateProps,
}: InfiniteHitsProps) => {
const handleInsightsClick = createInsightsEventHandler({
insights,
sendEvent,
});

if (results.hits.length === 0) {
return (
<Template
{...templateProps}
templateKey="empty"
rootProps={{
className: cx(cssClasses.root, cssClasses.emptyRoot),
onClick: handleInsightsClick,
}}
data={results}
/>
);
}

return (
<div className={cssClasses.root}>
<div className={cssClasses.root} onClick={handleInsightsClick}>
{hasShowPrevious && (
<Template
{...templateProps}
Expand Down
28 changes: 1 addition & 27 deletions packages/instantsearch.js/src/helpers/__tests__/insights-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
*/

import { warning, serializePayload } from '../../lib/utils';
import insights, {
writeDataAttributes,
readDataAttributes,
hasDataAttributes,
} from '../insights';
import insights, { writeDataAttributes, readDataAttributes } from '../insights';

const makeDomElement = (html: string): HTMLElement => {
const div = document.createElement('div');
Expand Down Expand Up @@ -92,28 +88,6 @@ describe('writeDataAttributes', () => {
});
});

describe('hasDataAttributes', () => {
it('should return true when there is a data-insights-method attribute', () => {
const domElement = makeDomElement(
`<button
data-insights-method="clickedObjectIDsAfterSearch"
data-insights-payload='{"objectIDs":["3"],"eventName":"Add to Cart"}'
> Add to Cart </button>`
);

expect(hasDataAttributes(domElement)).toBe(true);
});
it("should return false when there isn't a data-insights-method attribute", () => {
const domElement = makeDomElement(
`<button
data-insights-payload='{"objectIDs":["3"],"eventName":"Add to Cart"}'
> Add to Cart </button>`
);

expect(hasDataAttributes(domElement)).toBe(false);
});
});

describe('readDataAttributes', () => {
describe('on handwritten data-insights-* attributes', () => {
let domElement: HTMLElement;
Expand Down
6 changes: 2 additions & 4 deletions packages/instantsearch.js/src/helpers/insights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { warning, serializePayload, deserializePayload } from '../lib/utils';

import type { InsightsClientMethod, InsightsClientPayload } from '../types';

/** @deprecated use bindEvent instead */
export function readDataAttributes(domElement: HTMLElement): {
method: InsightsClientMethod;
payload: Partial<InsightsClientPayload>;
Expand Down Expand Up @@ -29,10 +30,7 @@ export function readDataAttributes(domElement: HTMLElement): {
}
}

export function hasDataAttributes(domElement: HTMLElement): boolean {
return domElement.hasAttribute('data-insights-method');
}

/** @deprecated use bindEvent instead */
export function writeDataAttributes({
method,
payload,
Expand Down
174 changes: 0 additions & 174 deletions packages/instantsearch.js/src/lib/__tests__/insights-listener-test.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createSingleSearchResponse } from '@instantsearch/mocks';
import { SearchParameters, SearchResults } from 'algoliasearch-helper';

import { createInstantSearch } from '../../../test/createInstantSearch';
import { withInsights, inferInsightsPayload } from '../insights';
import { withInsights, inferInsightsPayload } from '../';
import { createInstantSearch } from '../../../../test/createInstantSearch';

import type { InstantSearch, Widget } from '../../types';
import type { InstantSearch, Widget } from '../../../types';

const connectHits =
(renderFn: any, unmountFn: any) =>
Expand Down
Loading

0 comments on commit b4e9504

Please sign in to comment.