diff --git a/browser/DocumentRenderer.js b/browser/DocumentRenderer.js
index 66143d5..1a7c11f 100644
--- a/browser/DocumentRenderer.js
+++ b/browser/DocumentRenderer.js
@@ -145,6 +145,7 @@ class DocumentRenderer {
const id = this._getId(element);
const localContext = this._localContextProvider.getContextById(id);
const hadChildrenNodes = (element.children.length > 0);
+ let isInitialRender = false;
if (!renderingContext) {
renderingContext = this._createRenderingContext();
@@ -161,6 +162,7 @@ class DocumentRenderer {
const ComponentConstructor = localContext.constructor;
if (!instance) {
+ isInitialRender = true;
ComponentConstructor.prototype.$context = this._getComponentContext(localContext, element);
instance = new ComponentConstructor(this._locator);
instance.$context = ComponentConstructor.prototype.$context;
@@ -169,64 +171,73 @@ class DocumentRenderer {
this._componentElements[id] = element;
- return Promise.resolve()
- .then(() => {
- // we need to unbind the whole hierarchy only at
- // the beginning, not for any new elements
- if (!(id in renderingContext.rootIds) || !hadChildrenNodes) {
+ const shouldComponentUpdateMethod = moduleHelper.getMethodToInvoke(instance, 'shouldComponentUpdate');
+
+ return moduleHelper.getSafePromise(shouldComponentUpdateMethod)
+ .then((isShouldComponentUpdate = true) => {
+ if (!isShouldComponentUpdate && !isInitialRender) {
return null;
}
- return this._unbindAll(element, renderingContext);
- })
- .catch((reason) => this._eventBus.emit('error', reason))
- .then(() => this._bindWatcher(localContext, element))
- .then(() => {
- const renderMethod = moduleHelper.getMethodToInvoke(instance, 'render');
- return moduleHelper.getSafePromise(renderMethod);
- })
- .then((dataContext) => instance.template(dataContext))
- .catch((reason) => this._handleRenderError(element, reason))
- .then(html => {
- const isHead = element.tagName === TAG_NAMES.HEAD;
+ return Promise.resolve()
+ .then(() => {
+ // we need to unbind the whole hierarchy only at
+ // the beginning, not for any new elements
+ if (!(id in renderingContext.rootIds) || !hadChildrenNodes) {
+ return null;
+ }
- if (html === '' && isHead) {
- return null;
- }
+ return this._unbindAll(element, renderingContext);
+ })
+ .catch((reason) => this._eventBus.emit('error', reason))
+ .then(() => this._bindWatcher(localContext, element))
+ .then(() => {
+ const renderMethod = moduleHelper.getMethodToInvoke(instance, 'render');
+ return moduleHelper.getSafePromise(renderMethod);
+ })
+ .then((dataContext) => instance.template(dataContext))
+ .catch((reason) => this._handleRenderError(element, reason))
+ .then(html => {
+ const isHead = element.tagName === TAG_NAMES.HEAD;
+
+ if (html === '' && isHead) {
+ return null;
+ }
- const tmpElement = element.cloneNode(false);
- tmpElement.innerHTML = html;
+ const tmpElement = element.cloneNode(false);
+ tmpElement.innerHTML = html;
- this._updateSlotContent(tmpElement);
+ this._updateSlotContent(tmpElement);
- if (isHead) {
- this._mergeHead(element, tmpElement);
- return null;
- }
+ if (isHead) {
+ this._mergeHead(element, tmpElement);
+ return null;
+ }
- morphdom(element, tmpElement, {
- onBeforeMorphElChildren: (foundElement) =>
- foundElement === element || !moduleHelper.isComponentNode(foundElement)
- });
+ morphdom(element, tmpElement, {
+ onBeforeMorphElChildren: (foundElement) =>
+ foundElement === element || !moduleHelper.isComponentNode(foundElement)
+ });
- // Morphing slot elements
- let slot = findSlot(element);
- let fragment = this._componentSlotContents[id];
+ // Morphing slot elements
+ let slot = findSlot(element);
+ let fragment = this._componentSlotContents[id];
- if (slot && fragment) {
- let content = fragment.cloneNode(true);
+ if (slot && fragment) {
+ let content = fragment.cloneNode(true);
- Array.from(content.children)
- .forEach((child) => {
- child.$parentId = this._localContextProvider.getParentById(id);
- });
+ Array.from(content.children)
+ .forEach((child) => {
+ child.$parentId = this._localContextProvider.getParentById(id);
+ });
- slot.innerHTML = '';
- slot.appendChild(content);
- }
+ slot.innerHTML = '';
+ slot.appendChild(content);
+ }
+ })
+ .then(() => this._bindComponent(element));
})
- .then(() => this._bindComponent(element))
- .catch(reason => this._eventBus.emit('error', reason));
+ .catch((reason) => this._eventBus.emit('error', reason));
};
return this._traverseComponentsWithContext([rootElement], action, rootContext)
diff --git a/test/browser/DocumentRenderer.js b/test/browser/DocumentRenderer.js
index 27e3cc1..5e7a027 100644
--- a/test/browser/DocumentRenderer.js
+++ b/test/browser/DocumentRenderer.js
@@ -426,6 +426,93 @@ lab.experiment('browser/DocumentRenderer', () => {
});
});
+ lab.test('Should block render if shouldComponentUpdate return false', (done) => {
+ const locator = createLocator();
+ const eventBus = locator.resolve('eventBus');
+ let renderCount = 0;
+
+ const expected = 'test