diff --git a/docs/_js/examples/markdown.js b/docs/_js/examples/markdown.js index 7ea69a61477a1..04dd50997542c 100644 --- a/docs/_js/examples/markdown.js +++ b/docs/_js/examples/markdown.js @@ -25,7 +25,7 @@ var MarkdownEditor = React.createClass({\n\

Output

\n\ \n\ diff --git a/docs/docs/02.2-jsx-gotchas.md b/docs/docs/02.2-jsx-gotchas.md index 57280079db3af..f2b7a737820d3 100644 --- a/docs/docs/02.2-jsx-gotchas.md +++ b/docs/docs/02.2-jsx-gotchas.md @@ -49,7 +49,7 @@ You can use mixed arrays with strings and JSX elements. As a last resort, you always have the ability to insert raw HTML. ```javascript -
+
``` diff --git a/docs/docs/ref-04-tags-and-attributes.md b/docs/docs/ref-04-tags-and-attributes.md index c0d0108190c2a..6e782ebe8b4f5 100644 --- a/docs/docs/ref-04-tags-and-attributes.md +++ b/docs/docs/ref-04-tags-and-attributes.md @@ -70,7 +70,7 @@ In addition, the following non-standard attributes are supported: - `property` for [Open Graph](http://ogp.me/) meta tags. - `itemProp itemScope itemType` for [HTML5 microdata](http://schema.org/docs/gs.html). -There is also the React-specific attribute `dangerouslySetInnerHTML` ([more here](/react/docs/special-non-dom-attributes.html)), used for directly inserting HTML strings into a component. +There is also the React-specific attribute `dangerousInnerHTML` ([more here](/react/docs/special-non-dom-attributes.html)), used for directly inserting HTML strings into a component. ### SVG Attributes diff --git a/docs/docs/ref-07-special-non-dom-attributes.md b/docs/docs/ref-07-special-non-dom-attributes.md index 38e3ce8ea43e9..10341a3001739 100644 --- a/docs/docs/ref-07-special-non-dom-attributes.md +++ b/docs/docs/ref-07-special-non-dom-attributes.md @@ -10,4 +10,4 @@ Beside [DOM differences](/react/docs/dom-differences.html), React offers some at - `key`: an optional, unique identifier. When your component shuffles around during `render` passes, it might be destroyed and recreated due to the diff algorithm. Assigning it a key that persists makes sure the component stays. See more [here](/react/docs/multiple-components.html#dynamic-children). - `ref`: see [here](/react/docs/more-about-refs.html). -- `dangerouslySetInnerHTML`: takes an object with the key `__html` and a DOM string as value. This is mainly for cooperating with DOM string manipulation libraries. Refer to the last example on the front page. +- `dangerousInnerHTML`: takes an object with the key `__html` and a DOM string as value. This is mainly for cooperating with DOM string manipulation libraries. Refer to the last example on the front page. diff --git a/docs/docs/tutorial.md b/docs/docs/tutorial.md index 8ca60436d441a..2b2f97b48611e 100644 --- a/docs/docs/tutorial.md +++ b/docs/docs/tutorial.md @@ -257,7 +257,7 @@ var Comment = React.createClass({

{this.props.author}

- +
); } diff --git a/src/browser/ui/ReactDOMComponent.js b/src/browser/ui/ReactDOMComponent.js index 276be2e93b841..350f64eb87e83 100644 --- a/src/browser/ui/ReactDOMComponent.js +++ b/src/browser/ui/ReactDOMComponent.js @@ -36,6 +36,7 @@ var keyOf = require('keyOf'); var merge = require('merge'); var mixInto = require('mixInto'); var monitorCodeUse = require('monitorCodeUse'); +var warning = require('warning'); var deleteListener = ReactBrowserEventEmitter.deleteListener; var listenTo = ReactBrowserEventEmitter.listenTo; @@ -57,8 +58,12 @@ function assertValidProps(props) { } // Note the use of `==` which checks for null or undefined. invariant( - props.children == null || props.dangerouslySetInnerHTML == null, - 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' + props.children == null || props.dangerousInnerHTML == null, + 'Can only set one of `children` or `dangerousInnerHTML`.' + ); + invariant( + props.dangerousInnerHTML == null || props.dangerouslySetInnerHTML == null, + 'Can only set one of `dangerousInnerHTML` or `dangerouslySetInnerHTML`.' ); invariant( props.style == null || typeof props.style === 'object', @@ -67,6 +72,14 @@ function assertValidProps(props) { ); } +function warnForDeprecatedDangerouslySetInnerHTML(props) { + warning( + props.dangerouslySetInnerHTML == null, + '`dangerouslySetInnerHTML` is deprecated. Use ' + + '`dangerousInnerHTML` instead.' + ); +} + function putListener(id, registrationName, listener, transaction) { if (__DEV__) { // IE8 has no API for event capturing and the `onScroll` event doesn't @@ -194,7 +207,11 @@ ReactDOMComponent.Mixin = { */ _createContentMarkup: function(transaction) { // Intentional use of != to avoid catching zero/false. - var innerHTML = this.props.dangerouslySetInnerHTML; + var innerHTML = this.props.dangerousInnerHTML; + if (innerHTML == null) { + innerHTML = this.props.dangerouslySetInnerHTML; + warnForDeprecatedDangerouslySetInnerHTML(this.props); + } if (innerHTML != null) { if (innerHTML.__html != null) { return innerHTML.__html; @@ -371,11 +388,22 @@ ReactDOMComponent.Mixin = { CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null; var lastHtml = - lastProps.dangerouslySetInnerHTML && - lastProps.dangerouslySetInnerHTML.__html; + lastProps.dangerousInnerHTML && + lastProps.dangerousInnerHTML.__html; var nextHtml = - nextProps.dangerouslySetInnerHTML && - nextProps.dangerouslySetInnerHTML.__html; + nextProps.dangerousInnerHTML && + nextProps.dangerousInnerHTML.__html; + + if (lastHtml == null) { + lastHtml = + lastProps.dangerouslySetInnerHTML && + lastProps.dangerouslySetInnerHTML.__html; + } + if (nextHtml == null) { + nextHtml = + nextProps.dangerouslySetInnerHTML && + nextProps.dangerouslySetInnerHTML.__html; + } // Note the use of `!=` which checks for null or undefined. var lastChildren = lastContent != null ? null : lastProps.children; @@ -397,6 +425,9 @@ ReactDOMComponent.Mixin = { } } else if (nextHtml != null) { if (lastHtml !== nextHtml) { + if (lastHtml == null) { + warnForDeprecatedDangerouslySetInnerHTML(nextProps); + } ReactComponent.BackendIDOperations.updateInnerHTMLByID( this._rootNodeID, nextHtml diff --git a/src/browser/ui/ReactDOMIDOperations.js b/src/browser/ui/ReactDOMIDOperations.js index ea206cd065b90..1907d4c1fd35d 100644 --- a/src/browser/ui/ReactDOMIDOperations.js +++ b/src/browser/ui/ReactDOMIDOperations.js @@ -37,6 +37,8 @@ var setInnerHTML = require('setInnerHTML'); * @private */ var INVALID_PROPERTY_ERRORS = { + dangerousInnerHTML: + '`dangerousInnerHTML` must be set using `updateInnerHTMLByID()`.', dangerouslySetInnerHTML: '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.', style: '`style` must be set using `updateStylesByID()`.' diff --git a/src/browser/ui/__tests__/ReactDOMComponent-test.js b/src/browser/ui/__tests__/ReactDOMComponent-test.js index ef971bbac6116..49ecf9ee466e9 100644 --- a/src/browser/ui/__tests__/ReactDOMComponent-test.js +++ b/src/browser/ui/__tests__/ReactDOMComponent-test.js @@ -157,7 +157,7 @@ describe('ReactDOMComponent', function() { it("should empty element when removing innerHTML", function() { var stub = ReactTestUtils.renderIntoDocument( -
+
); expect(stub.getDOMNode().innerHTML).toEqual(':)'); @@ -172,7 +172,7 @@ describe('ReactDOMComponent', function() { expect(stub.getDOMNode().innerHTML).toEqual('hello'); stub.receiveComponent( - {props: {dangerouslySetInnerHTML: {__html: 'goodbye'}}}, + {props: {dangerousInnerHTML: {__html: 'goodbye'}}}, transaction ); expect(stub.getDOMNode().innerHTML).toEqual('goodbye'); @@ -180,7 +180,7 @@ describe('ReactDOMComponent', function() { it("should transition from innerHTML to string content", function() { var stub = ReactTestUtils.renderIntoDocument( -
+
); expect(stub.getDOMNode().innerHTML).toEqual('bonjour'); @@ -298,10 +298,10 @@ describe('ReactDOMComponent', function() { }); }); - it("should handle dangerouslySetInnerHTML", function() { + it("should handle dangerousInnerHTML", function() { var innerHTML = {__html: 'testContent'}; expect( - genMarkup({ dangerouslySetInnerHTML: innerHTML }) + genMarkup({ dangerousInnerHTML: innerHTML }) ).toHaveInnerhtml('testContent'); }); }); @@ -339,10 +339,10 @@ describe('ReactDOMComponent', function() { it("should validate against multiple children props", function() { expect(function() { - mountComponent({ children: '', dangerouslySetInnerHTML: '' }); + mountComponent({ children: '', dangerousInnerHTML: '' }); }).toThrow( 'Invariant Violation: Can only set one of `children` or ' + - '`props.dangerouslySetInnerHTML`.' + '`dangerousInnerHTML`.' ); }); @@ -370,12 +370,12 @@ describe('ReactDOMComponent', function() { expect(function() { React.renderComponent( -
, +
, container ); }).toThrow( 'Invariant Violation: Can only set one of `children` or ' + - '`props.dangerouslySetInnerHTML`.' + '`dangerousInnerHTML`.' ); }); diff --git a/src/browser/ui/__tests__/ReactDOMIDOperations-test.js b/src/browser/ui/__tests__/ReactDOMIDOperations-test.js index a1b93f04ec3aa..aebd182e260b4 100644 --- a/src/browser/ui/__tests__/ReactDOMIDOperations-test.js +++ b/src/browser/ui/__tests__/ReactDOMIDOperations-test.js @@ -33,7 +33,7 @@ describe('ReactDOMIDOperations', function() { expect(function() { ReactDOMIDOperations.updatePropertyByID( 'testID', - keyOf({dangerouslySetInnerHTML: null}), + keyOf({dangerousInnerHTML: null}), {__html: 'testContent'} ); }).toThrow(); diff --git a/src/browser/ui/dom/DOMPropertyOperations.js b/src/browser/ui/dom/DOMPropertyOperations.js index e4d562af856c7..cbd1bfe4fb025 100644 --- a/src/browser/ui/dom/DOMPropertyOperations.js +++ b/src/browser/ui/dom/DOMPropertyOperations.js @@ -40,6 +40,7 @@ var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { if (__DEV__) { var reactProps = { children: true, + dangerousInnerHTML: true, dangerouslySetInnerHTML: true, key: true, ref: true diff --git a/src/browser/ui/dom/components/ReactDOMTextarea.js b/src/browser/ui/dom/components/ReactDOMTextarea.js index 07b1377c952ce..82365fca0d4c2 100644 --- a/src/browser/ui/dom/components/ReactDOMTextarea.js +++ b/src/browser/ui/dom/components/ReactDOMTextarea.js @@ -106,8 +106,9 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ var props = merge(this.props); invariant( + props.dangerousInnerHTML == null && props.dangerouslySetInnerHTML == null, - '`dangerouslySetInnerHTML` does not make sense on