Do you want to request a feature or report a bug?
Maybe a bug?
What is the current behavior?
https://codesandbox.io/s/green-snow-79z65
When you give undefined to a direct attribute, it will use the defaultProp.
When you give undefined to an attribute of an object, it'll use this undefined
What is the expected behavior?
I'm not sure but I'm waiting for using the defaultProp even for an attribute of an object?
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
react 16.9.0
Hello @kud! I don't think it's a bug. You do provide an object { attribute: undefined } for your Components object property:
<Checker
object={{
attribute: undefined
}}
/>
so technically it isn't undefined anymore, and in that case defaultProps aren't applied.
You probably could just write your own getDefaultObject(props) function with custom logic merging your default object and props:
<Checker
object={getDefaultObject(props.object)}
/>
const defaultObject = { attribute: "attribute should be displayed too" }
function getDefaultObject(propsObject ) {
return { ...defaultObject, ...propsObject }
}
Of course if you want automatically merge objects of any shape you'll have to use some library or write your own method for traversing both object trees and merging, which could hit perfomance and I think that is the reason why defaultProps can't do it by its own.
Deep merging objects isn't really appropriate for a library to decide. If object had multiple mutually exclusive schemas, e.g. object={{ foo: true }} or object={{ bar: 30 }}, it would be wrong for the library to force a deep merging strategy.
Correct, React does not traverse objects when calculating props with defaultProps, so this is expected behavior.
Understood! Thanks for your kind explanation! :)
I'm still on it, sorry.
I've got a question.
Do you think so that using an object as props is finally a bad practice?
I wonder if I shouldn't make flat all my props now, to have the possibility to use "correctly" the defaultProps.
I don't think it's a bad practice. It's easier for default values or for controlling when your component should rerender, that is for sure.
For me it's all about the use case:
<Component x={10} y={y} /> // I prefer this
<Component dimensions={{ x: 10, y: 10 }} />
<Widget meta={props.meta} />
<Component
parser={props.parser}
printConfig={props.printConfig}
filters={props.filters}
pagination={props.pagination}
/>
instead of
<Component
parserProperty1={props.parser.property1}
/* ... */
paginationProperty99={props.pagination.property99}
/>
Of course, you could trick a bit the last case
<Component
{ ...props.parser }
{ ...props.printConfig }
{ ...props.filters }
{ ...props.pagination }
/>
But you still end up with a lot of properties to handle inside the component, and probably lose typings
I understand your point yes, thank you for this clear explanation.
Most helpful comment
I don't think it's a bad practice. It's easier for default values or for controlling when your component should rerender, that is for sure.
For me it's all about the use case:
instead of
Of course, you could trick a bit the last case
But you still end up with a lot of properties to handle inside the component, and probably lose typings