Default props inconsistency between React 19 and styled components

Author: andrey-ivlev-qsCreated Sep 1, 2026Updated Sep 1, 2026

The Context

React 19 has dropped FC.defaultProps (blog post) in favor of ES6 destructuring defaults. The react team suggests to move to the new syntax:

typescript
type Props = {
  type?: 'button' | 'submit' | 'reset';
  children?: ReactNode
}

// before
export const Button: FC<Props> = ({ type, children }) => {
  return <button type={type}>{children}</button>
}

Button.defaultProps = {
  type: 'button'
}

// after
export const Button: FC<Props> = ({ type = 'button', children }) => {
  return <button type={type}>{children}</button>
}

With Styled Components the similar effect can be archived by using function in .attrs():

typescript
export const StyledButton = styled.button
  .attrs(({ type = 'button', ...rest }) => ({ type, ...rest }))``

The Issue

Explicit undefined <StyledButton type={undefined} /> somehow ignores the default attribute value. This became quite painful when application code contains mixed styled / es6 components. It is impossible to predict which attribute value will be used without looking for the actual component implementation. Especially when components pass spread ...rest props like <StyledButton {...props} /> down to its grand- (grand-) children.

Reason for this issue

  • codebase contains two "defaultProps-flavored" types of components: es6-flavored and styled-flavored
  • hard to convert non-styled components to styled components (this requires finding all usages and checking for correct default values)

Possible solution

<StyledButton type={undefined} /> behaves the same way as <StyledButton /> which is the same as ES6 defaults and defaultProps

Source: styled-components/styled-components