Skip to content

Commit 547072f

Browse files
ftesdevelopit
authored andcommitted
[feature] replace undefined prop values with defaultProps (#60)
- mimick preact behaviour - fix #58
1 parent f4e1c9b commit 547072f

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

src/util.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,37 @@ export function styleObjToCss(s) {
3939
return str || undefined;
4040
}
4141

42+
/**
43+
* Copy all properties from `props` onto `obj`.
44+
* @param {object} obj Object onto which properties should be copied.
45+
* @param {object} props Object from which to copy properties.
46+
* @returns {object}
47+
* @private
48+
*/
4249
export function assign(obj, props) {
4350
for (let i in props) obj[i] = props[i];
4451
return obj;
4552
}
4653

54+
/**
55+
* Reconstruct Component-style `props` from a VNode.
56+
* Ensures default/fallback values from `defaultProps`:
57+
* Own-properties of `defaultProps` not present in `vnode.attributes` are added.
58+
* @param {import('preact').VNode} vnode The VNode to get props for
59+
* @returns {object} The props to use for this VNode
60+
*/
4761
export function getNodeProps(vnode) {
48-
let defaultProps = vnode.nodeName.defaultProps,
49-
props = assign({}, defaultProps || vnode.attributes);
50-
if (defaultProps) assign(props, vnode.attributes);
51-
if (vnode.children) props.children = vnode.children;
62+
let props = assign({}, vnode.attributes);
63+
props.children = vnode.children;
64+
65+
let defaultProps = vnode.nodeName.defaultProps;
66+
if (defaultProps!==undefined) {
67+
for (let i in defaultProps) {
68+
if (props[i]===undefined) {
69+
props[i] = defaultProps[i];
70+
}
71+
}
72+
}
73+
5274
return props;
5375
}

test/render.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,9 @@ describe('render', () => {
221221
};
222222

223223
expect(render(<Test />), 'defaults').to.equal('<div foo="default foo" bar="default bar"></div>');
224-
expect(render(<Test bar="b" />), 'partial').to.equal('<div foo="default foo" bar="b"></div>');
224+
expect(render(<Test bar="b" />), 'partial').to.equal('<div bar="b" foo="default foo"></div>');
225225
expect(render(<Test foo="a" bar="b" />), 'overridden').to.equal('<div foo="a" bar="b"></div>');
226+
expect(render(<Test foo={undefined} bar="b" />), 'overridden').to.equal('<div foo="default foo" bar="b"></div>');
226227
});
227228
});
228229

@@ -304,8 +305,9 @@ describe('render', () => {
304305
};
305306

306307
expect(render(<Test />), 'defaults').to.equal('<div foo="default foo" bar="default bar"></div>');
307-
expect(render(<Test bar="b" />), 'partial').to.equal('<div foo="default foo" bar="b"></div>');
308+
expect(render(<Test bar="b" />), 'partial').to.equal('<div bar="b" foo="default foo"></div>');
308309
expect(render(<Test foo="a" bar="b" />), 'overridden').to.equal('<div foo="a" bar="b"></div>');
310+
expect(render(<Test foo={undefined} bar="b" />), 'overridden').to.equal('<div foo="default foo" bar="b"></div>');
309311
});
310312

311313
it('should invoke componentWillMount', () => {

0 commit comments

Comments
 (0)