Skip to content

Commit

Permalink
Merge pull request algolia#934 from algolia/perf/url-refinement-list
Browse files Browse the repository at this point in the history
perf(refinementList): Stop creating URL for hidden refinements.
  • Loading branch information
Vincent Voyer committed Mar 24, 2016
2 parents 0bc1991 + 2cdd17d commit 212f522
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 45 deletions.
8 changes: 6 additions & 2 deletions src/components/RefinementList/RefinementList.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class RefinementList extends React.Component {
);
}

let templateData = {...facetValue, cssClasses: this.props.cssClasses};
let url = this.props.createURL(facetValue.name);
let templateData = {...facetValue, url, cssClasses: this.props.cssClasses};

let cssClassItem = cx(this.props.cssClasses.item, {
[this.props.cssClasses.active]: facetValue.isRefined
Expand Down Expand Up @@ -127,6 +128,8 @@ class RefinementList extends React.Component {
}

const limit = this.state.isShowMoreOpen ? this.props.limitMax : this.props.limitMin;
let displayedFacetValues = this.props.facetValues.slice(0, limit);

const showMoreBtn =
this.props.showMore ?
<Template
Expand All @@ -138,7 +141,7 @@ class RefinementList extends React.Component {

return (
<div className={cx(cssClassList)}>
{this.props.facetValues.map(this._generateFacetItem, this).slice(0, limit)}
{displayedFacetValues.map(this._generateFacetItem, this)}
{showMoreBtn}
</div>
);
Expand All @@ -148,6 +151,7 @@ class RefinementList extends React.Component {
RefinementList.propTypes = {
Template: React.PropTypes.func,
attributeNameKey: React.PropTypes.string,
createURL: React.PropTypes.func,
cssClasses: React.PropTypes.shape({
active: React.PropTypes.string,
depth: React.PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ describe('RefinementList', () => {
item: 'item',
active: 'active'
};
let templateData = {cssClasses};
let templateData = {
cssClasses,
url: 'url'
};
let commonItemProps = {
handleClick: () => {},
itemClassName: 'item',
Expand Down Expand Up @@ -139,6 +142,7 @@ describe('RefinementList', () => {
itemProps[0].subItems = (
<RefinementList
attributeNameKey="name"
createURL={() => {}}
cssClasses={customProps.cssClasses}
depth={1}
facetValues={customProps.facetValues[0].data}
Expand Down Expand Up @@ -173,6 +177,7 @@ describe('RefinementList', () => {
{name: 'facet1', isRefined: true},
{name: 'facet2', isRefined: false}
],
createURL: () => 'url',
...extraProps
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,9 @@ describe('hierarchicalMenu()', () => {
<RefinementList
attributeNameKey="path"
collapsible={false}
createURL={() => {}}
cssClasses={cssClasses}
facetValues={[{name: 'foo', url: '#'}, {name: 'bar', url: '#'}]}
facetValues={[{name: 'foo'}, {name: 'bar'}]}
shouldAutoHideContainer={false}
templateProps={templateProps}
toggleRefinement={() => {}}
Expand Down Expand Up @@ -349,13 +350,13 @@ describe('hierarchicalMenu()', () => {

data = {data: firstLevel};
let expectedFacetValues = [
{name: 'one', url: '#'},
{name: 'two', url: '#', data: [
{name: 'six', url: '#'},
{name: 'seven', url: '#'},
{name: 'eight', url: '#'}
{name: 'one'},
{name: 'two', data: [
{name: 'six'},
{name: 'seven'},
{name: 'eight'}
]},
{name: 'three', url: '#'}
{name: 'three'}
];
widget = hierarchicalMenu({...options, limit: 3});
widget.init({helper, createURL});
Expand Down
14 changes: 8 additions & 6 deletions src/widgets/hierarchical-menu/hierarchical-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,11 @@ function hierarchicalMenu({
Math.max(currentConfiguration.maxValuesPerFacet, limit) :
limit
}),
init({helper, templatesConfig, createURL}) {
init({helper, templatesConfig}) {
this._toggleRefinement = facetValue => helper
.toggleRefinement(hierarchicalFacetName, facetValue)
.search();

this._createURL = (state, facetValue) => createURL(state.toggleRefinement(hierarchicalFacetName, facetValue));

this._templateProps = prepareTemplateProps({
transformData,
defaultTemplates,
Expand All @@ -137,19 +135,23 @@ function hierarchicalMenu({
subValue.data = this._prepareFacetValues(subValue.data, state);
}

subValue.url = this._createURL(state, subValue);

return subValue;
});
},
render: function({results, state}) {
render: function({results, state, createURL}) {
let facetValues = results.getFacetValues(hierarchicalFacetName, {sortBy: sortBy}).data || [];
facetValues = this._prepareFacetValues(facetValues, state);

// Bind createURL to this specific attribute
function _createURL(facetValue) {
return createURL(state.toggleRefinement(hierarchicalFacetName, facetValue));
}

ReactDOM.render(
<RefinementList
attributeNameKey="path"
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={facetValues}
shouldAutoHideContainer={facetValues.length === 0}
Expand Down
8 changes: 7 additions & 1 deletion src/widgets/menu/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,19 @@ function menu({
return facetValue;
});
},
render: function({results, state}) {
render: function({results, state, createURL}) {
let facetValues = results.getFacetValues(hierarchicalFacetName, {sortBy: sortBy}).data || [];
facetValues = this._prepareFacetValues(facetValues, state);

// Bind createURL to this specific attribute
function _createURL(facetValue) {
return createURL(state.toggleRefinement(attributeName, facetValue));
}

ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={facetValues}
limitMax={widgetMaxValuesPerFacet}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,13 @@ describe('numericRefinementList()', () => {
root: 'ais-refinement-list root cx'
},
collapsible: false,
createURL: function() {},
facetValues: [
{attributeName: 'price', isRefined: true, name: 'All', url: '#'},
{attributeName: 'price', end: 4, isRefined: false, name: 'less than 4', url: '#'},
{attributeName: 'price', end: 4, isRefined: false, name: '4', start: 4, url: '#'},
{attributeName: 'price', end: 10, isRefined: false, name: 'between 5 and 10', start: 5, url: '#'},
{attributeName: 'price', isRefined: false, name: 'more than 10', start: 10, url: '#'}
{attributeName: 'price', isRefined: true, name: 'All'},
{attributeName: 'price', end: 4, isRefined: false, name: 'less than 4'},
{attributeName: 'price', end: 4, isRefined: false, name: '4', start: 4},
{attributeName: 'price', end: 10, isRefined: false, name: 'between 5 and 10', start: 5},
{attributeName: 'price', isRefined: false, name: 'more than 10', start: 10}
],
toggleRefinement: () => {},
shouldAutoHideContainer: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,18 @@ function numericRefinementList({
let facetValues = options.map(facetValue => {
facetValue.isRefined = isRefined(state, attributeName, facetValue);
facetValue.attributeName = attributeName;
facetValue.url = createURL(refine(state, attributeName, options, facetValue.name));
return facetValue;
});

// Bind createURL to this specific attribute
function _createURL(facetValue) {
return createURL(refine(state, attributeName, options, facetValue));
}

ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={facetValues}
shouldAutoHideContainer={results.nbHits === 0}
Expand Down
18 changes: 10 additions & 8 deletions src/widgets/refinement-list/refinement-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,29 +131,31 @@ function refinementList({

return widgetConfiguration;
},
init({templatesConfig, helper, createURL}) {
init({templatesConfig, helper}) {
this._templateProps = prepareTemplateProps({
transformData,
defaultTemplates,
templatesConfig,
templates: allTemplates
});
this._createURL = (state, facetValue) => createURL(state.toggleRefinement(attributeName, facetValue));

this.toggleRefinement = facetValue => helper
.toggleRefinement(attributeName, facetValue)
.search();
},
render: function({results, state}) {
render: function({results, state, createURL}) {
let facetValues = results
.getFacetValues(attributeName, {sortBy: sortBy})
.map(facetValue => {
facetValue.url = this._createURL(state, facetValue);
return facetValue;
});
.getFacetValues(attributeName, {sortBy: sortBy});

// Bind createURL to this specific attribute
function _createURL(facetValue) {
return createURL(state.toggleRefinement(attributeName, facetValue));
}

ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={facetValues}
limitMax={widgetMaxValuesPerFacet}
Expand Down
12 changes: 6 additions & 6 deletions src/widgets/star-rating/__tests__/star-rating-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ describe('starRating()', () => {
root: 'ais-star-rating'
},
collapsible: false,
createURL: () => {},
facetValues: [
{isRefined: false, stars: [true, true, true, true, false], count: 0, name: '4', labels: defaultLabels, url: '#'},
{isRefined: false, stars: [true, true, true, false, false], count: 0, name: '3', labels: defaultLabels, url: '#'},
{isRefined: false, stars: [true, true, false, false, false], count: 0, name: '2', labels: defaultLabels, url: '#'},
{isRefined: false, stars: [true, false, false, false, false], count: 0, name: '1', labels: defaultLabels, url: '#'}
{isRefined: false, stars: [true, true, true, true, false], count: 0, name: '4', labels: defaultLabels},
{isRefined: false, stars: [true, true, true, false, false], count: 0, name: '3', labels: defaultLabels},
{isRefined: false, stars: [true, true, false, false, false], count: 0, name: '2', labels: defaultLabels},
{isRefined: false, stars: [true, false, false, false, false], count: 0, name: '1', labels: defaultLabels}
],
toggleRefinement: () => {},
shouldAutoHideContainer: false,
Expand Down Expand Up @@ -120,8 +121,7 @@ describe('starRating()', () => {
isRefined: true,
name: '1',
stars: [true, false, false, false, false],
labels: defaultLabels,
url: '#'
labels: defaultLabels
}
]);
});
Expand Down
7 changes: 6 additions & 1 deletion src/widgets/star-rating/star-rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,19 @@ function starRating({
name: '' + star,
count: count,
isRefined: refinedStar === star,
url: createURL(state.toggleRefinement(attributeName, stars)),
labels
});
}

// Bind createURL to this specific attribute
function _createURL(facetValue) {
return createURL(state.toggleRefinement(attributeName, facetValue));
}

ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={facetValues}
shouldAutoHideContainer={results.nbHits === 0}
Expand Down
11 changes: 6 additions & 5 deletions src/widgets/toggle/__tests__/toggle-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe('toggle()', () => {
},
collapsible: false,
templateProps,
createURL: function() {},
toggleRefinement: function() {}
};
createURL = () => '#';
Expand Down Expand Up @@ -148,11 +149,11 @@ describe('toggle()', () => {
results = {
hits: [{Hello: ', world!'}],
nbHits: 1,
getFacetValues: sinon.stub().returns([{name: 'true', count: 2, url: '#'}, {name: 'false', count: 1, url: '#'}])
getFacetValues: sinon.stub().returns([{name: 'true', count: 2}, {name: 'false', count: 1}])
};
props.cssClasses.root += ' root cx';
props = {
facetValues: [{count: 1, isRefined: false, name: label, url: '#'}],
facetValues: [{count: 1, isRefined: false, name: label}],
shouldAutoHideContainer: false,
...props
};
Expand All @@ -175,7 +176,7 @@ describe('toggle()', () => {
widget.render({results, helper, state, createURL});

props = {
facetValues: [{count: 1, isRefined: false, name: label, url: '#'}],
facetValues: [{count: 1, isRefined: false, name: label}],
shouldAutoHideContainer: false,
...props
};
Expand All @@ -196,7 +197,7 @@ describe('toggle()', () => {
widget.render({results, helper, state, createURL});

props = {
facetValues: [{name: label, isRefined: false, count: null, url: '#'}],
facetValues: [{name: label, isRefined: false, count: null}],
shouldAutoHideContainer: true,
...props
};
Expand All @@ -222,7 +223,7 @@ describe('toggle()', () => {
widget.render({results, helper, state, createURL});

props = {
facetValues: [{count: 2, isRefined: true, name: label, url: '#'}],
facetValues: [{count: 2, isRefined: true, name: label}],
shouldAutoHideContainer: false,
...props
};
Expand Down
9 changes: 7 additions & 2 deletions src/widgets/toggle/toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,18 @@ function toggle({
let facetValue = {
name: label,
isRefined: isRefined,
count: values && values.count || null,
url: createURL(state.toggleRefinement(attributeName, isRefined))
count: values && values.count || null
};

// Bind createURL to this specific attribute
function _createURL() {
return createURL(state.toggleRefinement(attributeName, isRefined));
}

ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={_createURL}
cssClasses={cssClasses}
facetValues={[facetValue]}
shouldAutoHideContainer={results.nbHits === 0}
Expand Down

0 comments on commit 212f522

Please sign in to comment.