diff --git a/packages/react-instantsearch/src/core/utils.js b/packages/react-instantsearch/src/core/utils.js index 4b136a2d39..c16b1fc5de 100644 --- a/packages/react-instantsearch/src/core/utils.js +++ b/packages/react-instantsearch/src/core/utils.js @@ -1,4 +1,4 @@ -import { isEmpty } from 'lodash'; +import { isEmpty, isPlainObject } from 'lodash'; // From https://github.com/reactjs/react-redux/blob/master/src/utils/shallowEqual.js export function shallowEqual(objA, objB) { @@ -64,14 +64,13 @@ export const defer = f => { }; export function removeEmptyKey(obj) { - Object.keys(obj).forEach( - key => - (obj[key] && - typeof obj[key] === 'object' && - !isEmpty(obj[key]) && - removeEmptyKey(obj[key])) || - obj[key] === undefined || - (isEmpty(obj[key]) && delete obj[key]) - ); + Object.keys(obj).forEach(key => { + const value = obj[key]; + if (isEmpty(value) && isPlainObject(value)) { + delete obj[key]; + } else if (isPlainObject(value)) { + removeEmptyKey(value); + } + }); return obj; } diff --git a/packages/react-instantsearch/src/core/utils.test.js b/packages/react-instantsearch/src/core/utils.test.js index 75f28ed45c..9b4153d7b9 100644 --- a/packages/react-instantsearch/src/core/utils.test.js +++ b/packages/react-instantsearch/src/core/utils.test.js @@ -8,6 +8,7 @@ import { assertFacetDefined, getDisplayName, defer, + removeEmptyKey, } from './utils'; import { SearchParameters, SearchResults } from 'algoliasearch-helper'; @@ -110,4 +111,65 @@ describe('utils', () => { }); }); }); + describe('remove empty key', () => { + it('empty key should be removed', () => { + const state = { + query: '', + page: 2, + sortBy: 'mostPopular', + range: { + price: { + min: 20, + max: 3000, + }, + }, + refinementList: {}, + indices: { + index1: { + configure: { + hitsPerPage: 3, + refinementList: {}, + }, + }, + index2: { + configure: { + hitsPerPage: 10, + }, + refinementList: { + fruits: ['lemon', 'orange'], + }, + }, + }, + }; + + const newState = removeEmptyKey(state); + + expect(newState).toEqual({ + query: '', + page: 2, + sortBy: 'mostPopular', + range: { + price: { + min: 20, + max: 3000, + }, + }, + indices: { + index1: { + configure: { + hitsPerPage: 3, + }, + }, + index2: { + configure: { + hitsPerPage: 10, + }, + refinementList: { + fruits: ['lemon', 'orange'], + }, + }, + }, + }); + }); + }); });