Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

fix(createInstantSearchManager): fix multi-index search #2570

Merged
merged 8 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,12 @@ describe('createInstantSearchManager with multi index', () => {
// <SearchBox defaultRefinement="first query 1" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('first query 1'),
context: {},
props: {},
});

// <Index indexName="first" indexId="first" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first',
Expand All @@ -66,18 +64,16 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'first',
},
},
props: {},
});

// <Index indexName="second" indexId="second" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
context: {},
props: {
indexName: 'second',
indexId: 'second',
Expand All @@ -89,12 +85,11 @@ describe('createInstantSearchManager with multi index', () => {
// </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);
Expand Down Expand Up @@ -171,14 +166,12 @@ describe('createInstantSearchManager with multi index', () => {
// <SearchBox defaultRefinement="query" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('query'),
context: {},
props: {},
});

// <Index indexName="first" indexId="first" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first',
Expand All @@ -190,18 +183,16 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('third'),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'first',
},
},
props: {},
});

// <Index indexName="second" indexId="second" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('second'),
context: {},
props: {
indexName: 'second',
indexId: 'second',
Expand Down Expand Up @@ -249,7 +240,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="first" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first',
Expand All @@ -259,7 +249,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="second" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('second'),
context: {},
props: {
indexName: 'second',
indexId: 'second',
Expand All @@ -269,7 +258,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="third" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('third'),
context: {},
props: {
indexName: 'third',
indexId: 'third',
Expand All @@ -279,7 +267,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="four" />
ism.widgetsManager.registerWidget({
getSearchParameters: x => x.setIndex('four'),
context: {},
props: {
indexName: 'four',
indexId: 'four',
Expand Down Expand Up @@ -327,7 +314,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="first" indexId="first_5_hits" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first_5_hits',
Expand All @@ -339,18 +325,16 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQueryParameter('hitsPerPage', 5),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'first_5_hits',
},
},
props: {},
});

// <Index indexName="first" indexId="first_10_hits" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first_10_hits',
Expand All @@ -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);
Expand Down Expand Up @@ -415,14 +398,12 @@ describe('createInstantSearchManager with multi index', () => {
// <SearchBox defaultRefinement="first query 1" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('first query 1'),
context: {},
props: {},
});

// <Index indexName="first" indexId="first" />
const unregisterFirstIndexWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first',
Expand All @@ -434,18 +415,16 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
const unregisterPaginationWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'first',
},
},
props: {},
});

// <Index indexName="second" indexId="second" />
const unregisterSecondIndexWidget = ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
context: {},
props: {
indexName: 'second',
indexId: 'second',
Expand All @@ -457,12 +436,11 @@ describe('createInstantSearchManager with multi index', () => {
// </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);
Expand Down Expand Up @@ -506,7 +484,6 @@ describe('createInstantSearchManager with multi index', () => {
// <Index indexName="first" indexId="first" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('first'),
context: {},
props: {
indexName: 'first',
indexId: 'first',
Expand All @@ -518,18 +495,16 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setPage(3),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'first',
},
},
props: {},
});

// <Index indexName="second" indexId="second" />
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setIndex('second'),
context: {},
props: {
indexName: 'second',
indexId: 'second',
Expand All @@ -541,12 +516,11 @@ describe('createInstantSearchManager with multi index', () => {
// </Index>
ism.widgetsManager.registerWidget({
getSearchParameters: params => params.setQuery('second query 2'),
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'second',
},
},
props: {},
});

await runAllMicroTasks();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,6 @@ describe('createInstantSearchManager', () => {
getSearchParameters(state) {
return state.setIndex('index');
},
context: {},
props: {
indexId: 'index_with_refinement',
},
Expand All @@ -588,12 +587,11 @@ describe('createInstantSearchManager', () => {
getSearchParameters(state) {
return state.setQuery('derived');
},
context: {
multiIndexContext: {
props: {
indexContextValue: {
targetedIndex: 'index_with_refinement',
},
},
props: {},
});

const { mainParameters, derivedParameters } = ism.getSearchParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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] || [];
Expand Down
10 changes: 6 additions & 4 deletions packages/react-instantsearch-core/src/widgets/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -57,7 +57,7 @@ type State = {
class Index extends Component<InnerProps, State> {
static propTypes = {
indexName: PropTypes.string.isRequired,
indexId: PropTypes.string,
indexId: PropTypes.string.isRequired,
children: PropTypes.node,
};

Expand Down Expand Up @@ -125,7 +125,9 @@ class Index extends Component<InnerProps, State> {

const IndexWrapper: React.FC<Props> = props => (
<InstantSearchConsumer>
{contextValue => <Index contextValue={contextValue} {...props} />}
{contextValue => (
<Index contextValue={contextValue} indexId={props.indexName} {...props} />
Haroenv marked this conversation as resolved.
Show resolved Hide resolved
)}
</InstantSearchConsumer>
);

Expand Down