Skip to content

Commit 410459c

Browse files
author
Alexandre Stanislawski
committed
feat(connector): connectInfiniteHits (iteration 2)
1 parent bca09af commit 410459c

File tree

7 files changed

+98
-111
lines changed

7 files changed

+98
-111
lines changed

src/connectors/infinite-hits/__tests__/connectInfiniteHits-test.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
import sinon from 'sinon';
42

53
import jsHelper from 'algoliasearch-helper';
@@ -42,9 +40,6 @@ describe('connectInfiniteHits', () => {
4240
// test if isFirstRendering is true during init
4341
expect(rendering.lastCall.args[1]).toBe(true);
4442

45-
const firstRenderingOptions = rendering.lastCall.args[0];
46-
expect(firstRenderingOptions.containerNode).toBe(container);
47-
4843
widget.render({
4944
results: new SearchResults(helper.state, [{
5045
hits: [],
@@ -57,9 +52,6 @@ describe('connectInfiniteHits', () => {
5752
// test that rendering has been called during init with isFirstRendering = false
5853
expect(rendering.callCount).toBe(2);
5954
expect(rendering.lastCall.args[1]).toBe(false);
60-
61-
const secondRenderingOptions = rendering.lastCall.args[0];
62-
expect(secondRenderingOptions.containerNode).toBe(container);
6355
});
6456

6557
it('Provides the hits and the whole results', () => {

src/connectors/infinite-hits/connectInfiniteHits.js

Lines changed: 4 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,25 @@
1-
import {
2-
bemHelper,
3-
prepareTemplateProps,
4-
getContainerNode,
5-
} from '../../lib/utils.js';
6-
import cx from 'classnames';
7-
import defaultTemplates from './defaultTemplates.js';
8-
9-
const bem = bemHelper('ais-infinite-hits');
10-
11-
/**
12-
* Display the list of results (hits) from the current search
13-
* @function hits
14-
* @param {string|DOMElement} options.container CSS Selector or DOMElement to insert the widget
15-
* @param {number} [options.hitsPerPage=20] The number of hits to display per page [*]
16-
* @param {Object} [options.templates] Templates to use for the widget
17-
* @param {string|Function} [options.templates.empty=''] Template to use when there are no results.
18-
* @param {string|Function} [options.templates.item=''] Template to use for each result. This template will receive an object containing a single record.
19-
* @param {Object} [options.transformData] Method to change the object passed to the templates
20-
* @param {Function} [options.transformData.empty] Method used to change the object passed to the `empty` template
21-
* @param {Function} [options.transformData.item] Method used to change the object passed to the `item` template
22-
* @param {Object} [options.cssClasses] CSS classes to add
23-
* @param {string|string[]} [options.cssClasses.root] CSS class to add to the wrapping element
24-
* @param {string|string[]} [options.cssClasses.empty] CSS class to add to the wrapping element when no results
25-
* @param {string|string[]} [options.7cssClasses.item] CSS class to add to each result
26-
* @return {Object}
27-
*/
28-
const usage = `
29-
Usage:
30-
infiniteHits({
31-
container,
32-
[ cssClasses.{root,empty,item}={} ],
33-
[ templates.{empty,item} | templates.{empty} ],
34-
[ transformData.{empty,item} | transformData.{empty} ],
35-
[ hitsPerPage=20 ]
36-
})`;
371
const connectInfiniteHits = infiniteHitsRendering => ({
38-
container,
39-
cssClasses: userCssClasses = {},
402
showMoreLabel = 'Show more results',
41-
templates = defaultTemplates,
42-
transformData,
433
hitsPerPage = 20,
444
} = {}) => {
45-
if (!container) {
46-
throw new Error(`Must provide a container.${usage}`);
47-
}
48-
49-
const containerNode = getContainerNode(container);
50-
const cssClasses = {
51-
root: cx(bem(null), userCssClasses.root),
52-
item: cx(bem('item'), userCssClasses.item),
53-
empty: cx(bem(null, 'empty'), userCssClasses.empty),
54-
showmore: cx(bem('showmore'), userCssClasses.showmore),
55-
};
56-
575
let hitsCache = [];
58-
596
const getShowMore = helper => () => helper.nextPage().search();
607

618
return {
629
getConfiguration: () => ({hitsPerPage}),
63-
init({templatesConfig, helper}) {
64-
this._templateProps = prepareTemplateProps({
65-
transformData,
66-
defaultTemplates,
67-
templatesConfig,
68-
templates,
69-
});
70-
10+
init({instantSearchInstance, helper}) {
7111
this.showMore = getShowMore(helper);
7212

7313
infiniteHitsRendering({
74-
cssClasses,
7514
hits: hitsCache,
7615
results: undefined,
7716
showMore: this.showMore,
7817
showMoreLabel,
79-
templateProps: this._templateProps,
80-
containerNode,
8118
isLastPage: true,
19+
instantSearchInstance,
8220
}, true);
8321
},
84-
render({results, state}) {
22+
render({results, state, instantSearchInstance}) {
8523
if (state.page === 0) {
8624
hitsCache = [];
8725
}
@@ -91,14 +29,12 @@ const connectInfiniteHits = infiniteHitsRendering => ({
9129
const isLastPage = results.nbPages <= results.page + 1;
9230

9331
infiniteHitsRendering({
94-
cssClasses,
9532
hits: hitsCache,
9633
results,
9734
showMore: this.showMore,
9835
showMoreLabel,
99-
templateProps: this._templateProps,
100-
containerNode,
10136
isLastPage,
37+
instantSearchInstance,
10238
}, false);
10339
},
10440
};

src/widgets/hits/__tests__/defaultTemplates-test.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
2-
3-
4-
import defaultTemplates from '../../../connectors/hits/defaultTemplates.js';
1+
import defaultTemplates from '../defaultTemplates.js';
52

63
describe('hits defaultTemplates', () => {
74
it('has a `empty` default template', () => {

src/widgets/infinite-hits/__tests__/defaultTemplates-test.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
2-
3-
4-
import defaultTemplates from '../../../connectors/infinite-hits/defaultTemplates.js';
1+
import defaultTemplates from '../defaultTemplates.js';
52

63
describe('hits defaultTemplates', () => {
74
it('has a `empty` default template', () => {

src/widgets/infinite-hits/__tests__/infinite-hits-test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ expect.extend(expectJSX);
66
import algoliasearchHelper from 'algoliasearch-helper';
77
import infiniteHits from '../infinite-hits';
88
import InfiniteHits from '../../../components/InfiniteHits';
9-
import defaultTemplates from '../../../connectors/infinite-hits/defaultTemplates.js';
9+
import defaultTemplates from '../defaultTemplates.js';
1010

1111
describe('infiniteHits call', () => {
1212
it('throws an exception when no container', () => {
13-
expect(infiniteHits).toThrow(/^Must provide a container/);
13+
expect(infiniteHits).toThrow();
1414
});
1515
});
1616

@@ -38,7 +38,7 @@ describe('infiniteHits()', () => {
3838
useCustomCompileOptions: {item: false, empty: false},
3939
};
4040
widget = infiniteHits({container, cssClasses: {root: ['root', 'cx']}});
41-
widget.init({helper});
41+
widget.init({helper, instantSearchInstance: {}});
4242
results = {hits: [{first: 'hit', second: 'hit'}]};
4343
});
4444

File renamed without changes.

src/widgets/infinite-hits/infinite-hits.js

Lines changed: 89 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,56 @@ import React from 'react';
22
import ReactDOM from 'react-dom';
33
import InfiniteHits from '../../components/InfiniteHits.js';
44

5+
import {
6+
bemHelper,
7+
prepareTemplateProps,
8+
getContainerNode,
9+
} from '../../lib/utils.js';
10+
import cx from 'classnames';
11+
import defaultTemplates from './defaultTemplates.js';
12+
513
import connectInfiniteHits from '../../connectors/infinite-hits/connectInfiniteHits.js';
614

15+
const bem = bemHelper('ais-infinite-hits');
16+
17+
const renderer = ({
18+
cssClasses,
19+
containerNode,
20+
renderState,
21+
templates,
22+
transformData,
23+
}) => ({
24+
hits,
25+
results,
26+
showMore,
27+
showMoreLabel,
28+
isLastPage,
29+
instantSearchInstance,
30+
}, isFirstRendering) => {
31+
if (isFirstRendering) {
32+
renderState.templateProps = prepareTemplateProps({
33+
transformData,
34+
defaultTemplates,
35+
templatesConfig: instantSearchInstance.templatesConfig,
36+
templates,
37+
});
38+
return;
39+
}
40+
41+
ReactDOM.render(
42+
<InfiniteHits
43+
cssClasses={cssClasses}
44+
hits={hits}
45+
results={results}
46+
showMore={showMore}
47+
showMoreLabel={showMoreLabel}
48+
templateProps={renderState.templateProps}
49+
isLastPage={isLastPage}
50+
/>,
51+
containerNode
52+
);
53+
};
54+
755
/**
856
* Display the list of results (hits) from the current search
957
* @function infiniteHits
@@ -22,30 +70,47 @@ import connectInfiniteHits from '../../connectors/infinite-hits/connectInfiniteH
2270
* @param {string|string[]} [options.cssClasses.item] CSS class to add to each result
2371
* @return {Object}
2472
*/
25-
export default connectInfiniteHits(defaultRendering);
73+
const usage = `
74+
Usage:
75+
infiniteHits({
76+
container,
77+
[ cssClasses.{root,empty,item}={} ],
78+
[ templates.{empty,item} | templates.{empty} ],
79+
[ transformData.{empty,item} | transformData.{empty} ],
80+
[ hitsPerPage=20 ]
81+
})`;
2682

27-
function defaultRendering({
28-
cssClasses,
29-
hits,
30-
results,
31-
showMore,
32-
showMoreLabel,
33-
templateProps,
34-
isLastPage,
35-
containerNode,
36-
}, isFirstRendering) {
37-
if (isFirstRendering) return;
83+
export default function infiniteHits({
84+
container,
85+
cssClasses: userCssClasses = {},
86+
showMoreLabel = 'Show more results',
87+
templates = defaultTemplates,
88+
transformData,
89+
hitsPerPage = 20,
90+
}) {
91+
if (!container) {
92+
throw new Error(`Must provide a container.${usage}`);
93+
}
3894

39-
ReactDOM.render(
40-
<InfiniteHits
41-
cssClasses={cssClasses}
42-
hits={hits}
43-
results={results}
44-
showMore={showMore}
45-
showMoreLabel={showMoreLabel}
46-
templateProps={templateProps}
47-
isLastPage={isLastPage}
48-
/>,
49-
containerNode
50-
);
95+
const containerNode = getContainerNode(container);
96+
const cssClasses = {
97+
root: cx(bem(null), userCssClasses.root),
98+
item: cx(bem('item'), userCssClasses.item),
99+
empty: cx(bem(null, 'empty'), userCssClasses.empty),
100+
showmore: cx(bem('showmore'), userCssClasses.showmore),
101+
};
102+
103+
const specializedRenderer = renderer({
104+
containerNode,
105+
cssClasses,
106+
transformData,
107+
templates,
108+
renderState: {},
109+
});
110+
111+
const makeInfiniteHits = connectInfiniteHits(specializedRenderer);
112+
return makeInfiniteHits({
113+
showMoreLabel,
114+
hitsPerPage,
115+
});
51116
}

0 commit comments

Comments
 (0)