react icon indicating copy to clipboard operation
react copied to clipboard

Bug: Regression with defaultProps on class components

Open henryqdineen opened this issue 1 year ago • 1 comments

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 avatar Dec 07 '24 03:12 henryqdineen

@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>; }

adi-ydv-1 avatar Dec 07 '24 12:12 adi-ydv-1

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!

github-actions[bot] avatar Mar 07 '25 13:03 github-actions[bot]

bump. I still consider it an undocumented breaking change.

henryqdineen avatar Mar 07 '25 17:03 henryqdineen

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>
  );
}

paer avatar Jun 04 '25 13:06 paer

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!

github-actions[bot] avatar Sep 02 '25 13:09 github-actions[bot]

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).

balzss avatar Sep 02 '25 16:09 balzss

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

matyasf avatar Sep 03 '25 07:09 matyasf

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

jaroslav-kubicek avatar Oct 02 '25 12:10 jaroslav-kubicek

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!

github-actions[bot] avatar Dec 31 '25 12:12 github-actions[bot]

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!

github-actions[bot] avatar Jan 07 '26 12:01 github-actions[bot]

this bug is still present afaik, is it possible to reopen this and not create a new one for the same issue?

balzss avatar Jan 07 '26 14:01 balzss