diff --git a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js index 22f83a1c2a..f91322ba37 100644 --- a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js +++ b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js @@ -163,7 +163,8 @@ var HTMLDOMPropertyConfig = { tabIndex: null, target: null, title: null, - type: null, + // Setting .type throws on non- tags + type: MUST_USE_ATTRIBUTE, useMap: null, value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS, width: MUST_USE_ATTRIBUTE, diff --git a/src/renderers/dom/shared/ReactDOMComponent.js b/src/renderers/dom/shared/ReactDOMComponent.js index f482bbf43d..31fe153be0 100644 --- a/src/renderers/dom/shared/ReactDOMComponent.js +++ b/src/renderers/dom/shared/ReactDOMComponent.js @@ -937,7 +937,8 @@ ReactDOMComponent.Mixin = { var styleUpdates; for (propKey in lastProps) { if (nextProps.hasOwnProperty(propKey) || - !lastProps.hasOwnProperty(propKey)) { + !lastProps.hasOwnProperty(propKey) || + lastProps[propKey] == null) { continue; } if (propKey === STYLE) { @@ -967,7 +968,9 @@ ReactDOMComponent.Mixin = { var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps[propKey]; - if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) { + if (!nextProps.hasOwnProperty(propKey) || + nextProp === lastProp || + nextProp == null && lastProp == null) { continue; } if (propKey === STYLE) { diff --git a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js index ac042eaa4d..7e6c78b9ce 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js @@ -426,6 +426,24 @@ describe('ReactDOMComponent', function() { ReactDOM.render(, container); expect(container.firstChild.hasAttribute('cowabunga')).toBe(true); }); + + it('should not update when switching between null/undefined', function() { + var container = document.createElement('div'); + var node = ReactDOM.render(
, container); + + var setter = mocks.getMockFunction(); + Object.defineProperty(node, 'dir', { + get: function() {}, + set: setter, + }); + + ReactDOM.render(, container); + ReactDOM.render(, container); + ReactDOM.render(, container); + expect(setter.mock.calls.length).toBe(0); + ReactDOM.render(, container); + expect(setter.mock.calls.length).toBe(1); + }); }); describe('createOpenTagMarkup', function() {