Skip to content

Commit

Permalink
fix(transformData): always call transformData (#1555)
Browse files Browse the repository at this point in the history
Event when data does not changes, we now call transformData, so that
if the transformedData changes, there will be a new render.

fixes #1538
  • Loading branch information
vvo committed Nov 16, 2016
1 parent e4d88e0 commit 49bfeca
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ describe('RefinementList', () => {

// When
const root = shallowRender(props);
const actual = root.find('Template').filter({templateKey: 'show-more-inactive'});
const actual = root.find('[templateKey="show-more-inactive"]');

// Then
expect(actual.length).toEqual(1);
Expand Down
17 changes: 14 additions & 3 deletions src/components/Template.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import hogan from 'hogan.js';

import isEqual from 'lodash/isEqual';

class Template extends React.Component {
export class Template extends React.Component {
shouldComponentUpdate(nextProps) {
return !isEqual(this.props.data, nextProps.data) || this.props.templateKey !== nextProps.templateKey;
}
Expand All @@ -22,7 +22,7 @@ class Template extends React.Component {
templateKey: this.props.templateKey,
compileOptions,
helpers: this.props.templatesConfig.helpers,
data: transformData(this.props.transformData, this.props.templateKey, this.props.data),
data: this.props.data,
});

if (content === null) {
Expand Down Expand Up @@ -137,4 +137,15 @@ function transformHelpersToHogan(helpers, compileOptions, data) {
);
}

export default Template;
// Resolve transformData before Template, so transformData is always called
// even if the data is the same. Allowing you to dynamically inject conditions in
// transformData that will force re-rendering
const withTransformData =
TemplateToWrap =>
props =>
<TemplateToWrap
{...props}
data={transformData(props.transformData, props.templateKey, props.data)} // eslint-disable-line react/prop-types
/>;

export default withTransformData(Template);
17 changes: 8 additions & 9 deletions src/components/__tests__/Template-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import expect from 'expect';
import TestUtils from 'react-addons-test-utils';
import Template from '../Template';
import TemplateWithTransformData, {Template} from '../Template';
import sinon from 'sinon';
import expectJSX from 'expect-jsx';
expect.extend(expectJSX);
Expand Down Expand Up @@ -120,11 +120,10 @@ describe('Template', () => {
},
});

renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);

const out = renderer.getRenderOutput();
const content = 'it supports transformData';
const expectedJSX = <div dangerouslySetInnerHTML={{__html: content}}></div>;
const expectedJSX = <Template {...props} data={{feature: 'transformData'}} />;

expect(out).toEqualJSX(expectedJSX);
});
Expand All @@ -144,7 +143,7 @@ describe('Template', () => {
},
});

renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);
expect(called).toBe(true);
});

Expand All @@ -165,7 +164,7 @@ describe('Template', () => {
},
});

renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);
expect(called).toBe(true);
});

Expand All @@ -177,7 +176,7 @@ describe('Template', () => {
});

expect(() => {
renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);
}).toThrow('`transformData` must return a `object`, got `undefined`.');
});

Expand All @@ -191,7 +190,7 @@ describe('Template', () => {
});

expect(() => {
renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);
}).toNotThrow();
});

Expand All @@ -203,7 +202,7 @@ describe('Template', () => {
});

expect(() => {
renderer.render(<Template {...props} />);
renderer.render(<TemplateWithTransformData {...props} />);
}).toThrow('`transformData` must return a `object`, got `boolean`.');
});
});
Expand Down
6 changes: 3 additions & 3 deletions src/decorators/__tests__/headerFooter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('headerFooter', () => {
const out = render(defaultProps);
// Then
const templateProps = {
data: {},
data: undefined,
templateKey: 'header',
transformData: null,
templates: {
Expand All @@ -90,7 +90,7 @@ describe('headerFooter', () => {
const out = render(defaultProps);
// Then
const templateProps = {
data: {},
data: undefined,
templateKey: 'footer',
transformData: null,
templates: {
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('headerFooter', () => {
footer: 'yo footer',
};
templateProps = {
data: {},
data: undefined,
transformData: null,
templates: {
header: 'yo header',
Expand Down
19 changes: 0 additions & 19 deletions src/widgets/refinement-list/__tests__/refinement-list-test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
/* eslint-env mocha */

import React from 'react';
import expect from 'expect';
import sinon from 'sinon';

import {createRenderer} from 'react-addons-test-utils';

import expectJSX from 'expect-jsx';
expect.extend(expectJSX);

import refinementList from '../refinement-list.js';
import Template from '../../../components/Template.js';
import createHelpers from '../../../lib/createHelpers.js';
import defaultTemplates from '../defaultTemplates.js';

describe('refinementList()', () => {
let autoHideContainer;
Expand All @@ -21,8 +15,6 @@ describe('refinementList()', () => {
let options;
let widget;
let ReactDOM;
const renderer = createRenderer();
const helpers = createHelpers('en-US');

beforeEach(() => {
container = document.createElement('div');
Expand Down Expand Up @@ -187,17 +179,6 @@ describe('refinementList()', () => {
createURL = () => '#';
});

it('formats counts', () => {
const props = {
templatesConfig: {helpers},
templates: defaultTemplates,
};
renderer.render(<Template data={{count: 1000}} {...props} templateKey="item" />);
const out = renderer.getRenderOutput();
// eslint-disable-next-line max-len
expect(out).toEqualJSX(<div dangerouslySetInnerHTML={{__html: '<label class="">\n <input type="checkbox" class="" value="" />\n <span class="">1,000</span>\n</label>'}} />);
});

context('cssClasses', () => {
it('should call the component with the correct classes', () => {
// Given
Expand Down
15 changes: 0 additions & 15 deletions src/widgets/toggle/implementations/__tests__/currentToggle-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@ import React from 'react';
import expect from 'expect';
import sinon from 'sinon';

import {createRenderer} from 'react-addons-test-utils';

import currentToggle from '../currentToggle.js';
import defaultTemplates from '../../defaultTemplates.js';
import Template from '../../../../components/Template';

import expectJSX from 'expect-jsx';
expect.extend(expectJSX);
import createHelpers from '../../../../lib/createHelpers.js';

describe('currentToggle()', () => {
const helpers = createHelpers('en-US');
const renderer = createRenderer();

context('good usage', () => {
let ReactDOM;
let containerNode;
Expand Down Expand Up @@ -102,14 +95,6 @@ describe('currentToggle()', () => {
expect(ReactDOM.render.secondCall.args[1]).toEqual(containerNode);
});

it('formats counts', () => {
templateProps.templatesConfig = {helpers};
renderer.render(<Template data={{count: 1000}} {...templateProps} templateKey="item" />);
const out = renderer.getRenderOutput();
// eslint-disable-next-line max-len
expect(out).toEqualJSX(<div dangerouslySetInnerHTML={{__html: '<label class="">\n <input type="checkbox" class="" value="" />\n <span class="">1,000</span>\n</label>'}} />);
});

it('understands cssClasses', () => {
results = {
hits: [{Hello: ', world!'}],
Expand Down

0 comments on commit 49bfeca

Please sign in to comment.