diff --git a/package.json b/package.json
index 738c4ab733..c1fc32f04f 100644
--- a/package.json
+++ b/package.json
@@ -129,7 +129,7 @@
},
{
"path": "packages/react-instantsearch/dist/umd/Connectors.min.js",
- "maxSize": "41.75 kB"
+ "maxSize": "41.80 kB"
},
{
"path": "packages/react-instantsearch/dist/umd/Dom.min.js",
diff --git a/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.derived.js b/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.derived.js
index e905767fc2..3e1e95e4a8 100644
--- a/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.derived.js
+++ b/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.derived.js
@@ -47,14 +47,12 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('first query 1'),
- context: {},
props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first',
@@ -66,18 +64,16 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first',
},
},
- props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
- context: {},
props: {
indexName: 'second',
indexId: 'second',
@@ -89,12 +85,11 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('second query 1'),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'second',
},
},
- props: {},
});
expect(ism.store.getState().results).toBe(null);
@@ -171,14 +166,12 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('query'),
- context: {},
props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first',
@@ -190,18 +183,16 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('third'),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first',
},
},
- props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('second'),
- context: {},
props: {
indexName: 'second',
indexId: 'second',
@@ -249,7 +240,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first',
@@ -259,7 +249,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('second'),
- context: {},
props: {
indexName: 'second',
indexId: 'second',
@@ -269,7 +258,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('third'),
- context: {},
props: {
indexName: 'third',
indexId: 'third',
@@ -279,7 +267,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('four'),
- context: {},
props: {
indexName: 'four',
indexId: 'four',
@@ -327,7 +314,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first_5_hits',
@@ -339,18 +325,16 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQueryParameter('hitsPerPage', 5),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first_5_hits',
},
},
- props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first_10_hits',
@@ -363,12 +347,11 @@ describe('createInstantSearchManager with multi index', () => {
ism.widgetsManager.registerWidget({
getSearchParameters: params =>
params.setQueryParameter('hitsPerPage', 10),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first_10_hits',
},
},
- props: {},
});
expect(ism.store.getState().results).toBe(null);
@@ -415,14 +398,12 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('first query 1'),
- context: {},
props: {},
});
//
const unregisterFirstIndexWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first',
@@ -434,18 +415,16 @@ describe('createInstantSearchManager with multi index', () => {
//
const unregisterPaginationWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first',
},
},
- props: {},
});
//
const unregisterSecondIndexWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
- context: {},
props: {
indexName: 'second',
indexId: 'second',
@@ -457,12 +436,11 @@ describe('createInstantSearchManager with multi index', () => {
//
const unregisterSecondSearchBoxWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('second query 1'),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'second',
},
},
- props: {},
});
expect(ism.store.getState().results).toBe(null);
@@ -506,7 +484,6 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
- context: {},
props: {
indexName: 'first',
indexId: 'first',
@@ -518,18 +495,16 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'first',
},
},
- props: {},
});
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
- context: {},
props: {
indexName: 'second',
indexId: 'second',
@@ -541,12 +516,11 @@ describe('createInstantSearchManager with multi index', () => {
//
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('second query 2'),
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'second',
},
},
- props: {},
});
await runAllMicroTasks();
diff --git a/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.js b/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.js
index f409962aa1..0e7c40a520 100644
--- a/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.js
+++ b/packages/react-instantsearch-core/src/core/__tests__/createInstantSearchManager.js
@@ -1,6 +1,17 @@
+import React from 'react';
+import Adapter from 'enzyme-adapter-react-16';
+import Enzyme, { mount } from 'enzyme';
import algoliasearch from 'algoliasearch/lite';
import { SearchResults } from 'algoliasearch-helper';
import createInstantSearchManager from '../createInstantSearchManager';
+import {
+ InstantSearch,
+ Index,
+ SortBy,
+ Configure,
+} from 'react-instantsearch-dom';
+
+Enzyme.configure({ adapter: new Adapter() });
jest.useFakeTimers();
@@ -575,7 +586,6 @@ describe('createInstantSearchManager', () => {
getSearchParameters(state) {
return state.setIndex('index');
},
- context: {},
props: {
indexId: 'index_with_refinement',
},
@@ -588,12 +598,11 @@ describe('createInstantSearchManager', () => {
getSearchParameters(state) {
return state.setQuery('derived');
},
- context: {
- multiIndexContext: {
+ props: {
+ indexContextValue: {
targetedIndex: 'index_with_refinement',
},
},
- props: {},
});
const { mainParameters, derivedParameters } = ism.getSearchParameters();
@@ -615,6 +624,126 @@ describe('createInstantSearchManager', () => {
},
]);
});
+
+ it('expects widgets main parameters and derived parameters to be correctly calculated within a multi index context', () => {
+ const wrapper = mount(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+
+ const {
+ mainParameters,
+ derivedParameters,
+ } = wrapper.instance().aisManager.getSearchParameters();
+
+ expect(mainParameters).toEqual(
+ expect.objectContaining({
+ index: 'index1',
+ })
+ );
+
+ expect(derivedParameters).toEqual([
+ expect.objectContaining({
+ indexId: 'bestbuy',
+ parameters: expect.objectContaining({
+ index: 'bestbuy',
+ }),
+ }),
+ expect.objectContaining({
+ indexId: 'instant_search',
+ parameters: expect.objectContaining({
+ index: 'instant_search',
+ }),
+ }),
+ expect.objectContaining({
+ indexId: 'instant_search_apple',
+ parameters: expect.objectContaining({
+ index: 'instant_search',
+ filters: 'brand:Apple',
+ }),
+ }),
+ expect.objectContaining({
+ indexId: 'instant_search_samsung',
+ parameters: expect.objectContaining({
+ index: 'instant_search',
+ filters: 'brand:Samsung',
+ }),
+ }),
+ expect.objectContaining({
+ indexId: 'instant_search_microsoft',
+ parameters: expect.objectContaining({
+ index: 'instant_search',
+ filters: 'brand:Microsoft',
+ }),
+ }),
+ ]);
+ });
+
+ it('expects widgets main parameters and derived parameters to be correctly calculated with SortBy within a multi index context', () => {
+ const wrapper = mount(
+
+
+
+
+
+
+
+
+
+ );
+
+ const {
+ mainParameters,
+ derivedParameters,
+ } = wrapper.instance().aisManager.getSearchParameters();
+
+ expect(mainParameters).toEqual(
+ expect.objectContaining({
+ index: 'index1',
+ })
+ );
+
+ expect(derivedParameters).toEqual([
+ expect.objectContaining({
+ indexId: 'categories',
+ parameters: expect.objectContaining({
+ index: 'bestbuy',
+ }),
+ }),
+ expect.objectContaining({
+ indexId: 'products',
+ parameters: expect.objectContaining({
+ index: 'brands',
+ }),
+ }),
+ ]);
+ });
});
describe('searchStalled', () => {
diff --git a/packages/react-instantsearch-core/src/core/createInstantSearchManager.js b/packages/react-instantsearch-core/src/core/createInstantSearchManager.js
index 6fd1976b34..dc77972f94 100644
--- a/packages/react-instantsearch-core/src/core/createInstantSearchManager.js
+++ b/packages/react-instantsearch-core/src/core/createInstantSearchManager.js
@@ -13,9 +13,13 @@ function addAlgoliaAgents(searchClient) {
}
}
-const isMultiIndexContext = widget => hasMultipleIndices(widget.context);
+const isMultiIndexContext = widget =>
+ hasMultipleIndices({
+ ais: widget.props.contextValue,
+ multiIndexContext: widget.props.indexContextValue,
+ });
const isTargetedIndexEqualIndex = (widget, indexId) =>
- widget.context.multiIndexContext.targetedIndex === indexId;
+ widget.props.indexContextValue.targetedIndex === indexId;
// Relying on the `indexId` is a bit brittle to detect the `Index` widget.
// Since it's a class we could rely on `instanceof` or similar. We never
@@ -24,6 +28,16 @@ const isIndexWidget = widget => Boolean(widget.props.indexId);
const isIndexWidgetEqualIndex = (widget, indexId) =>
widget.props.indexId === indexId;
+const sortIndexWidgetsFirst = (firstWidget, secondWidget) => {
+ if (isIndexWidget(firstWidget)) {
+ return -1;
+ }
+ if (isIndexWidget(secondWidget)) {
+ return 1;
+ }
+ return 0;
+};
+
/**
* Creates a new instance of the InstantSearchManager which controls the widgets and
* trigger the search when the widgets are updated.
@@ -114,6 +128,9 @@ export default function createInstantSearchManager({
return targetedIndexEqualMainIndex || subIndexEqualMainIndex;
})
+ // We have to sort the `Index` widgets first so the `index` parameter
+ // is correctly set in the `reduce` function for the following widgets
+ .sort(sortIndexWidgetsFirst)
.reduce(
(res, widget) => widget.getSearchParameters(res),
sharedParameters
@@ -132,9 +149,12 @@ export default function createInstantSearchManager({
return targetedIndexNotEqualMainIndex || subIndexNotEqualMainIndex;
})
+ // We have to sort the `Index` widgets first so the `index` parameter
+ // is correctly set in the `reduce` function for the following widgets
+ .sort(sortIndexWidgetsFirst)
.reduce((indices, widget) => {
const indexId = isMultiIndexContext(widget)
- ? widget.context.multiIndexContext.targetedIndex
+ ? widget.props.indexContextValue.targetedIndex
: widget.props.indexId;
const widgets = indices[indexId] || [];
diff --git a/packages/react-instantsearch-core/src/widgets/Index.tsx b/packages/react-instantsearch-core/src/widgets/Index.tsx
index b7d60dc4f1..9d10fcce37 100644
--- a/packages/react-instantsearch-core/src/widgets/Index.tsx
+++ b/packages/react-instantsearch-core/src/widgets/Index.tsx
@@ -9,13 +9,13 @@ import {
function getIndexContext(props: Props): IndexContext {
return {
- targetedIndex: props.indexId || props.indexName,
+ targetedIndex: props.indexId,
};
}
type Props = {
indexName: string;
- indexId?: string;
+ indexId: string;
};
type InnerProps = Props & { contextValue: InstantSearchContext };
@@ -57,7 +57,7 @@ type State = {
class Index extends Component {
static propTypes = {
indexName: PropTypes.string.isRequired,
- indexId: PropTypes.string,
+ indexId: PropTypes.string.isRequired,
children: PropTypes.node,
};
@@ -123,11 +123,20 @@ class Index extends Component {
}
}
-const IndexWrapper: React.FC = props => (
-
- {contextValue => }
-
-);
+const IndexWrapper: React.FC = props => {
+ const inferredIndexId = props.indexName;
+ return (
+
+ {contextValue => (
+
+ )}
+
+ );
+};
export const IndexComponentWithoutContext = Index;
export default IndexWrapper;