Skip to content

ButtonProps children type incompatible with React 19+ JSX ((state: PressableStateCallbackType) => ReactNode not assignable to ReactNode) #4032

@lucksp

Description

@lucksp

Is there an existing issue for this?

  • I have searched the existing issues

Explain what you did

Environment

@rneui/themed: 5.x
react: 19.2.0
@types/react: 19.0.8
React Native / Expo

Describe the bug

ButtonProps extends PressableProps from React Native, which types children as:
children?: ReactNode | ((state: PressableStateCallbackType) => ReactNode)

Since React 18, @types/react no longer accepts function children as ReactNode via JSX. This means any component that wraps <Button> and spreads ButtonProps via {...rest} gets a TypeScript error:

Type '(state: PressableStateCallbackType) => ReactNode' is not assignable to type 'ReactNode'

Steps to reproduce

Create a wrapper component that accepts and spreads ButtonProps:

import { Button as RNEButton, type ButtonProps } from '@rneui/themed';
const Button = ({ ...rest }: ButtonProps) => {
  return <RNEButton {...rest} />;
};

Workaround

type Props = Omit<ButtonProps, 'children'> & { children?: ReactNode };

And render children explicitly as JSX children rather than spreading them.

Suggested fix

Narrow children in ButtonProps (and potentially PressableProps-derived types across the library) to ReactNode only, dropping the render-prop variant since it's not a pattern the Button component actually uses publicly.

Expected behavior

No type error. The children prop on ButtonProps should be narrowed to ReactNode to be compatible with React 18/19 JSX types.

Describe the bug

Since Updating my components to use RNE v5, I noticed a TS error in the Button:
Type '(state: PressableStateCallbackType) => ReactNode' is not assignable to type 'ReactNode'

import { Button as RNEButton, type ButtonProps } from '@rneui/themed';
import React from 'react';

import { useStyles } from './style';

const Button = ({
  buttonStyle,
  containerStyle,
  type,
  disabledStyle,
  disabledTitleStyle,
  titleStyle,
  disabled,
  ...rest
}: ButtonProps) => {
  const styles = useStyles({ type, disabled });

  return (
    <RNEButton
      buttonStyle={[styles.button, buttonStyle]}
      containerStyle={[styles.buttonContainer, containerStyle]}
      disabled={disabled}
      disabledStyle={[disabledStyle]}
      disabledTitleStyle={[disabledTitleStyle]}
      titleStyle={[styles.title, titleStyle]}
      {...rest}
    />
  );
};

export { Button };

the workaround is to:

const Button = ({
  buttonStyle,
  containerStyle,
  type,
  disabledStyle,
  disabledTitleStyle,
  titleStyle,
  disabled,
  children,
  ...rest
}: Omit<ButtonProps, 'children'> & { children?: ReactNode }) => {
  const styles = useStyles({ type, disabled });

  return (
    <RNEButton
      buttonStyle={[styles.button, buttonStyle]}
      containerStyle={[styles.buttonContainer, containerStyle]}
      disabled={disabled}
      disabledStyle={[disabledStyle]}
      disabledTitleStyle={[disabledTitleStyle]}
      titleStyle={[styles.title, titleStyle]}
      {...rest}
    >
      {children}
    </RNEButton>
  );
};

export { Button };

Steps To Reproduce

Create a wrapper component that accepts and spreads ButtonProps:


import { Button as RNEButton, type ButtonProps } from '@rneui/themed';
const Button = ({ ...rest }: ButtonProps) => {
  return <RNEButton {...rest} />;
};

Screenshots

No response

Your Environment

`npx @rneui/envinfo`
  ```
    React Native Elements Env Info

Global Dependencies:

No related dependency found

Local Dependencies:

  • @rneui/base : ^5.0.0
  • @rneui/themed : ^5.0.0
  • expo : ^55.0.0
  • react : 19.2.0
  • react-native : 0.83.6
  • react-native-elements : ^3.4.3
    
    

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions