Skip to content

Commit 8fc0831

Browse files
bobylitoiam4x
authored andcommitted
feat(searchFunction): make search function provide a better API
* feat(searchFunction): Offer full helper support in search function This implementation offers: - a full helper to modify the parameters before sending the request - all the other search function (searchOnce, searchForFacetValues) - compatibility with async code (no oops effect) * fix(slider): Make sure the slider doesn't update the state twice This commit adds constraints to make sure that a refine call doesn't trigger a new state update and search. It also adds undefined as a value that can be passed as "no boundary selected" for min and max in the refine function (slider connector). * fix(searchFunction): rm unnecessary state update in internals * chore(naming): change name of search helper function * chore(test): test searchFunction in a less altered env The previous setup was not compatible with the kind of manipulation done for implementing the `searchFunction`.
1 parent dc68f46 commit 8fc0831

File tree

5 files changed

+75
-35
lines changed

5 files changed

+75
-35
lines changed

src/components/Slider/Slider.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ class Slider extends Component {
3535
return this.props.min === this.props.max;
3636
}
3737

38-
handleChange = ({values}) => {
38+
handleChange = ({min, max, values}) => {
3939
// when Slider is disabled, we alter `min, max` values
4040
// in order to render a "disabled state" Slider. Since we alter
4141
// theses values, Rheostat trigger a "change" event which trigger a new
4242
// search to Algolia with wrong values.
4343
if (!this.isDisabled) {
4444
const {refine} = this.props;
45-
refine(values);
45+
refine([
46+
min === values[0] ? undefined : values[0],
47+
max === values[1] ? undefined : values[1],
48+
]);
4649
}
4750
}
4851

src/connectors/range-slider/connectRangeSlider.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,21 @@ export default function connectRangeSlider(renderFn) {
119119

120120
init({helper, instantSearchInstance}) {
121121
this._refine = bounds => newValues => {
122-
helper.clearRefinements(attributeName);
123-
if (!bounds.min || newValues[0] > bounds.min) {
124-
helper.addNumericRefinement(attributeName, '>=', formatToNumber(newValues[0]));
122+
const currentValues = [
123+
helper.getNumericRefinement(attributeName, '>='),
124+
helper.getNumericRefinement(attributeName, '<='),
125+
];
126+
127+
if (currentValues[0] !== newValues[0] || currentValues[1] !== newValues[1]) {
128+
helper.clearRefinements(attributeName);
129+
if (!bounds.min || newValues[0] > bounds.min) {
130+
helper.addNumericRefinement(attributeName, '>=', formatToNumber(newValues[0]));
131+
}
132+
if (!bounds.max || newValues[1] < bounds.max) {
133+
helper.addNumericRefinement(attributeName, '<=', formatToNumber(newValues[1]));
134+
}
135+
helper.search();
125136
}
126-
if (!bounds.max || newValues[1] < bounds.max) {
127-
helper.addNumericRefinement(attributeName, '<=', formatToNumber(newValues[1]));
128-
}
129-
helper.search();
130137
};
131138

132139
const stats = {

src/lib/InstantSearch.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,19 +121,27 @@ Usage: instantsearch({
121121
);
122122

123123
if (this._searchFunction) {
124-
this.helper = Object.create(helper);
125-
this.helper.search = () => {
126-
helper.setState(this.helper.state);
127-
this._searchFunction(helper);
124+
this._mainHelperSearch = helper.search.bind(helper);
125+
helper.search = () => {
126+
const helperSearchFunction = algoliasearchHelper(
127+
{
128+
addAlgoliaAgent: () => {},
129+
search: () => {},
130+
},
131+
helper.state.index,
132+
helper.state
133+
);
134+
helperSearchFunction.once('search', state => {
135+
helper.overrideStateWithoutTriggeringChangeEvent(state);
136+
this._mainHelperSearch();
137+
});
138+
this._searchFunction(helperSearchFunction);
128139
};
129-
this._init(helper.state, this.helper);
130-
helper.on('result', this._render.bind(this, this.helper));
131-
} else {
132-
this.helper = helper;
133-
this._init(helper.state, this.helper);
134-
this.helper.on('result', this._render.bind(this, this.helper));
135140
}
136141

142+
this.helper = helper;
143+
this._init(helper.state, this.helper);
144+
this.helper.on('result', this._render.bind(this, this.helper));
137145
this.helper.search();
138146
}
139147

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import sinon from 'sinon';
2+
3+
// import algoliaSearchHelper from 'algoliasearch-helper';
4+
import InstantSearch from '../InstantSearch';
5+
6+
const appId = 'appId';
7+
const apiKey = 'apiKey';
8+
const indexName = 'lifecycle';
9+
10+
describe.only('InstantSearch lifecycle', () => {
11+
it('calls the provided searchFunction when used', () => {
12+
const searchFunctionSpy = sinon.spy(h => {
13+
h.setQuery('test').search();
14+
});
15+
16+
const fakeClient = {
17+
search: sinon.spy(),
18+
addAlgoliaAgent: () => {},
19+
};
20+
21+
const search = new InstantSearch({
22+
appId,
23+
apiKey,
24+
indexName,
25+
searchFunction: searchFunctionSpy,
26+
createAlgoliaClient: () => fakeClient,
27+
});
28+
29+
expect(searchFunctionSpy.callCount).toBe(0);
30+
expect(fakeClient.search.callCount).toBe(0);
31+
32+
search.start();
33+
34+
expect(searchFunctionSpy.callCount).toBe(1);
35+
expect(search.helper.state.query).toBe('test');
36+
expect(fakeClient.search.callCount).toBe(1);
37+
});
38+
});

src/lib/__tests__/InstantSearch-test.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,22 +125,6 @@ describe('InstantSearch lifecycle', () => {
125125
});
126126
});
127127

128-
it('calls the provided searchFunction when used', () => {
129-
const searchSpy = sinon.spy(h => {
130-
h.setQuery('test').search();
131-
});
132-
search = new InstantSearch({
133-
appId,
134-
apiKey,
135-
indexName,
136-
searchFunction: searchSpy,
137-
});
138-
search.start();
139-
expect(searchSpy.calledOnce).toBe(true);
140-
expect(helper.state.query).toBe('test');
141-
expect(helperSearchSpy.calledOnce).toBe(true);
142-
});
143-
144128
it('does not fail when passing same references inside multiple searchParameters props', () => {
145129
const disjunctiveFacetsRefinements = {fruits: ['apple']};
146130
const facetsRefinements = disjunctiveFacetsRefinements;

0 commit comments

Comments
 (0)