Bug: Regression with defaultProps on class components
React version: 19.0.0
Steps To Reproduce
According to the React 19 upgrade guide "Class components will continue to support defaultProps" but your code might break or behave differently if you are relying on the prop defaulting to happen on element creation (by the JSX runtime).
Consider this example:
class Foo extends Component {
static defaultProps = {
bar: "baz",
};
}
const element = <Foo />;
// works in React 18 only
expect(element.props.bar).toBe('baz');
This is an contrived and unrealistic scenario but we found actual code in a library where there was a <Table> component that read off props of <Column> child elements that expected to be defaulted.
Link to code example:
React 18: https://codesandbox.io/p/sandbox/confident-bose-ssmddt React 19: https://codesandbox.io/p/sandbox/zen-drake-n223m8
The current behavior
Props are not defaulted on element creation
The expected behavior
If we are going for backwards compatibility I would say the expected behavior is default props on element create if isReactComponent. I can see how that would be ugly and a step backwards through but this quirk and undocument breaking change can definitely cause some hard to track down bugs
@henryqdineen It is not a bug but a major update from React 18.3 ..yeah you didn't like it but i hope to react team did it to make react faster and Instead of using default props, you can use JavaScript default parameters or object destructuring to default your component's props
function Greeting({ name = '<unknown>' }) { return <h1>Hello, {name}!</h1>; }
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
bump. I still consider it an undocumented breaking change.
It still works in react 19, when accessing props in the class itself:
(modified code from codesandbox above)
import "./styles.css";
import { Component, ReactNode } from "react";
class Foo extends Component {
static defaultProps = {
bar: "baz",
};
render(): ReactNode {
return this.props.bar; // Will be present in both React 18 and 19
}
}
export default function App() {
const element = <Foo />;
return (
<pre>
{/* React 18: baz, React 19: baz */}
{element}
{/* React 18: {"bar": "baz"}, React 19: {} */}
{JSON.stringify(element.props, null, 2)}
</pre>
);
}
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
I'm in the middle of upgrading instructure/instructure-ui from react 18 to react 19 and this is causing us major headaches. This issue was really helpful for debugging.
In our repo (which is a react component library, monorepo, almost exclusively class components) we use an emotion based decorator for styling our component which generates a HOC with relevant styling data. It should "forward" the defaultProps but looks like it doesn't for the reasons @henryqdineen described.
This change is not documented and I also consider it to be a bug as it doesn't have a good alternative (or if it does, I'd like to know it).
So the default value is not there on creation, but it exist on render. When is it added exactly? I would also consider this a breaking change, a codemod (if possible) could help users with the 18-19 upgrade
We're in the middle of the upgrade to React 19 as well, and it caused problems too. Either it should be included in the list of breaking changes or be mentioned in the upgrade guide: https://react.dev/blog/2024/04/25/react-19-upgrade-guide
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!
this bug is still present afaik, is it possible to reopen this and not create a new one for the same issue?