I'm trying to set a defaultProp with an object literal, but after some time I realized that the React class constructor is not merging the default props with the applied props, so I end up with undefined values for any properties in the defaultProps literal that haven't been included in the applied props. Is there a way to merge default props and applied props, or do I need to break up my object into several props?
class Test extends React.Component {
constructor(props) {
super(props);
//props.test is only {one: false}
//props.test.two is undefined
}
render() {
return (<div>render</div>)
}
}
Test.defaultProps = {
test: {
one: true,
two: true
}
}
ReactDOM.render(<Test test={{'one': false}}/>, document.getElementById('#test'));
http://codepen.io/adjavaherian/pen/oYNPLz
React only does a shallow merge of the default props and the actual props, i.e. nested default props are overridden instead of merged. This is by design.
See this React issue for more background and reasoning why this is the case and potential workarounds:
aside from the potential perf issues here. one issue with this is how do you handle nested complex structures like arrays? concatenation? Union? what about an array of objects? deep object merging can lead to unexpected behaviour, which is why often implementations allow you to specify a merge strategy such as _. merge. I'm not sure how you would do that in prop type declaration.
This is kind of late to answer but I couldn't find any official or better ways to assign default props
that way so that the props would be merged with the defaults!
I did it in my own way as shown below:
defaultProps
variable before the rendering function or classconst var = Object.assign({}, defaultProps.var , props.var);
to get the props object var merged with the default variable var.
Of course, you should do a little more coding for nested objects and arrays to make this approach go well! the assign
function is for shallow merging.
The best approach is using _.merge
function of *loadash library.
App.propTypes
and App.defaultProps
import React from 'react';
import PropTypes from 'prop-types';
const defaultProps = {
user: {
id: 0,
name: 'Mike',
family: 'wheeler',
},
address: {
addr1: 'Saint Louis, Arsenal Street',
addr2: '',
tel: null,
},
color: 'orange',
weight: 60,
age: 20,
};
.
.
.
export default function App(props){
const {color, weight, age} = props;
const user = Object.assign({}, defaultProps.user , props.user);
const address = Object.assign({}, defaultProps.address, props.address);
return (<div></div>);
}
App.propTypes = {
type: PropTypes.string.isRequired,
user: PropTypes.shape({
id: PropTypes.number,
name: PropTypes.string,
family: PropTypes.string,
}),
address: PropTypes.shape({
addr1: PropTypes.string,
addr2: PropTypes.string,
tel: PropTypes.string,
}),
color: PropTypes.string,
weight: PropTypes.number,
age: PropTypes.number,
};
App.defaultProps = defaultProps;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With