Skip to content

Commit

Permalink
Merge pull request #3372 from jonhester/void-elements
Browse files Browse the repository at this point in the history
ReactDOMComponent should throw error when provided children for void elements
  • Loading branch information
jimfb committed Jan 29, 2016
2 parents 67e1291 + aca4ccd commit 9d5825c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 50 deletions.
24 changes: 11 additions & 13 deletions src/renderers/dom/shared/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,19 +142,17 @@ function assertValidProps(component, props) {
return;
}
// Note the use of `==` which checks for null or undefined.
if (__DEV__) {
if (voidElementTags[component._tag]) {
warning(
props.children == null && props.dangerouslySetInnerHTML == null,
'%s is a void element tag and must not have `children` or ' +
'use `props.dangerouslySetInnerHTML`.%s',
component._tag,
component._currentElement._owner ?
' Check the render method of ' +
component._currentElement._owner.getName() + '.' :
''
);
}
if (voidElementTags[component._tag]) {
invariant(
props.children == null && props.dangerouslySetInnerHTML == null,
'%s is a void element tag and must not have `children` or ' +
'use `props.dangerouslySetInnerHTML`.%s',
component._tag,
component._currentElement._owner ?
' Check the render method of ' +
component._currentElement._owner.getName() + '.' :
''
);
}
if (props.dangerouslySetInnerHTML != null) {
invariant(
Expand Down
77 changes: 40 additions & 37 deletions src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -852,43 +852,44 @@ describe('ReactDOMComponent', function() {
});

it('should warn against children for void elements', function() {
spyOn(console, 'error');

var container = document.createElement('div');

ReactDOM.render(<input>children</input>, container);

expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain('void element');
expect(function() {
ReactDOM.render(<input>children</input>, container);
}).toThrow(
'input is a void element tag and must not have `children` or ' +
'use `props.dangerouslySetInnerHTML`.'
);
});

it('should warn against dangerouslySetInnerHTML for void elements', function() {
spyOn(console, 'error');

var container = document.createElement('div');

ReactDOM.render(
<input dangerouslySetInnerHTML={{__html: 'content'}} />,
container
expect(function() {
ReactDOM.render(
<input dangerouslySetInnerHTML={{__html: 'content'}} />,
container
);
}).toThrow(
'input is a void element tag and must not have `children` or use ' +
'`props.dangerouslySetInnerHTML`.'
);

expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain('void element');
});

it('should treat menuitem as a void element but still create the closing tag', function() {
spyOn(console, 'error');

var container = document.createElement('div');

var returnedValue = ReactDOMServer.renderToString(<menu><menuitem /></menu>);

expect(returnedValue).toContain('</menuitem>');

ReactDOM.render(<menu><menuitem>children</menuitem></menu>, container);
expect(function() {
ReactDOM.render(<menu><menuitem>children</menuitem></menu>, container);
}).toThrow(
'menuitem is a void element tag and must not have `children` or use ' +
'`props.dangerouslySetInnerHTML`.'
);

expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain('void element');
});

it('should validate against multiple children props', function() {
Expand Down Expand Up @@ -1006,17 +1007,17 @@ describe('ReactDOMComponent', function() {
});

it('should warn for children on void elements', function() {
spyOn(console, 'error');
var X = React.createClass({
render: function() {
return <input>moo</input>;
},
});

var container = document.createElement('div');
ReactDOM.render(<X />, container);
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toBe(
'Warning: input is a void element tag and must not have `children` ' +
expect(function() {
ReactDOM.render(<X />, container);
}).toThrow(
'input is a void element tag and must not have `children` ' +
'or use `props.dangerouslySetInnerHTML`. Check the render method of X.'
);
});
Expand All @@ -1030,26 +1031,28 @@ describe('ReactDOMComponent', function() {
});

it('should warn against children for void elements', function() {
spyOn(console, 'error');

ReactDOM.render(<input />, container);
ReactDOM.render(<input>children</input>, container);

expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain('void element');
expect(function() {
ReactDOM.render(<input>children</input>, container);
}).toThrow(
'input is a void element tag and must not have `children` or use ' +
'`props.dangerouslySetInnerHTML`.'
);
});

it('should warn against dangerouslySetInnerHTML for void elements', function() {
spyOn(console, 'error');

ReactDOM.render(<input />, container);
ReactDOM.render(
<input dangerouslySetInnerHTML={{__html: 'content'}} />,
container
);

expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain('void element');
expect(function() {
ReactDOM.render(
<input dangerouslySetInnerHTML={{__html: 'content'}} />,
container
);
}).toThrow(
'input is a void element tag and must not have `children` or use ' +
'`props.dangerouslySetInnerHTML`.'
);
});

it('should validate against multiple children props', function() {
Expand Down

0 comments on commit 9d5825c

Please sign in to comment.