Default props inconsistency between React 19 and styled components
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:
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():
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