Skip to content

Commit c4dc71e

Browse files
authored
Fix nullish default props (#4775)
1 parent 3c556ad commit c4dc71e

File tree

6 files changed

+28
-3
lines changed

6 files changed

+28
-3
lines changed

jsx-runtime/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function createVNode(type, props, key, isStaticChildren, __source, __self) {
6969
// Note: `type` is often a String, and can be `undefined` in development.
7070
if (typeof type === 'function' && (ref = type.defaultProps)) {
7171
for (i in ref)
72-
if (typeof normalizedProps[i] === 'undefined') {
72+
if (normalizedProps[i] === undefined) {
7373
normalizedProps[i] = ref[i];
7474
}
7575
}

jsx-runtime/test/browser/jsx-runtime.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ describe('Babel jsx/jsxDEV', () => {
6868
});
6969
});
7070

71+
it('should respect defaultProps when props are null', () => {
72+
const Component = ({ children }) => children;
73+
Component.defaultProps = { foo: 'bar' };
74+
expect(jsx(Component, { foo: null }).props).to.deep.equal({ foo: null });
75+
});
76+
7177
it('should keep props over defaultProps', () => {
7278
class Foo extends Component {
7379
render() {

src/clone-element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function cloneElement(vnode, props, children) {
2626
for (i in props) {
2727
if (i == 'key') key = props[i];
2828
else if (i == 'ref') ref = props[i];
29-
else if (props[i] == UNDEFINED && defaultProps != UNDEFINED) {
29+
else if (props[i] === UNDEFINED && defaultProps != UNDEFINED) {
3030
normalizedProps[i] = defaultProps[i];
3131
} else {
3232
normalizedProps[i] = props[i];

src/create-element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function createElement(type, props, children) {
3333
// Note: type may be undefined in development, must never error here.
3434
if (typeof type == 'function' && type.defaultProps != NULL) {
3535
for (i in type.defaultProps) {
36-
if (normalizedProps[i] == UNDEFINED) {
36+
if (normalizedProps[i] === UNDEFINED) {
3737
normalizedProps[i] = type.defaultProps[i];
3838
}
3939
}

test/browser/cloneElement.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,17 @@ describe('cloneElement', () => {
9797
const clone = cloneElement(element, { color: undefined });
9898
expect(clone.props.color).to.equal('blue');
9999
});
100+
101+
it('should prevent undefined properties from overriding default props', () => {
102+
class Example extends Component {
103+
render(props) {
104+
return <div style={{ color: props.color }}>thing</div>;
105+
}
106+
}
107+
Example.defaultProps = { color: 'blue' };
108+
109+
const element = <Example color="red" />;
110+
const clone = cloneElement(element, { color: null });
111+
expect(clone.props.color).to.equal(null);
112+
});
100113
});

test/shared/createElement.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ describe('createElement(jsx)', () => {
271271
expect(h(Component, null).props).to.deep.equal({ foo: 'bar' });
272272
});
273273

274+
it('should respect defaultProps when props are null', () => {
275+
const Component = ({ children }) => children;
276+
Component.defaultProps = { foo: 'bar' };
277+
expect(h(Component, { foo: null }).props).to.deep.equal({ foo: null });
278+
});
279+
274280
it('should override defaultProps', () => {
275281
const Component = ({ children }) => children;
276282
Component.defaultProps = { foo: 'default' };

0 commit comments

Comments
 (0)