skip to Main Content

Are there any significant differences between those two ways to define props in React.FunctionalComponent?

interface Props {
    username: string,
    age: number
}

const UserPanel: React.FunctionComponent = (props: Props) => (
    <div>{props.username}</div>
);

const UserPanel: React.FunctionComponent<Props> = (props) => (
    <div>{props.age}</div>
);

2

Answers


  1. Yes, a quite significant difference: Option one is throwing away type information.

    The function on the right hand side includes information about the props, but then you assign it to a variable that does not have that information. UserPanel‘s type uses the default props of {} so whoever uses UserPanel can not pass in any props. Attempting to pass in a username prop or age prop will throw an error. For example:

    const UserPanel: React.FunctionComponent = (props: Props) => (
        <div>{props.username}</div>
    );
    
    const SomeOtherCmponent = () => {
      // Error: Type '{ username: string; age: number; }' is not assignable to type 'IntrinsicAttributes'.
      return <UserPanel username="foo" age={100}/>
    }
    

    Playground link

    You either need to do your second option:

    const UserPanel: React.FunctionComponent<Props> = (props) => (
        <div>{props.age}</div>
    );
    

    Or you need to do this:

    const UserPanel = (props: Props) => (
        <div>{props.age}</div>
    );
    
    Login or Signup to reply.
  2. The first ways to define props in React.functionComponent will emit an error:

    Type '(props: Props) => JSX.Element' is not assignable to type 'FunctionComponent<{}>'.
      Types of parameters 'props' and 'props' are incompatible.
        Type '{}' is missing the following properties from type 'Props': username, agets(2322)
    

    If we look into the type definition of React.FunctionComponent (in my case React v18.2.45) we’ll see:

    interface FunctionComponent<P = {}> {
        (props: P, context?: any): ReactNode;
        propTypes?: WeakValidationMap<P> | undefined;
        contextTypes?: ValidationMap<any> | undefined;
        defaultProps?: Partial<P> | undefined;
        displayName?: string | undefined;
    }
    

    Basically, the error tells us that the definition of the props in React.FunctionComponent {} does not match the definition of interface Props { name: string, age: number } which you passed in.

    Let’s explain the type definition of props in React.FunctionComponent.

    • P = {} : This is a generic parameter. It represents the props that the function component expects. By default, it’s an empty object, meaning no props are expected.
    • (props: P, context?: any): ReactNode: This is the function signature for the component. It takes two parameters: props and context. props is of type P (the props the component expects), and context is optional and can be of any type. The function returns a ReactNode, which can be any valid React child (a React element, string, number, etc.).

    Because in React.FunctionComponent, props is expecting the generic type P (which is {}), you have to define the generic type P inorder to pass into UserPanel component. This is where your second way to define props in React.FunctionComponent comes in.

    const UserPanel: React.FunctionComponent<Props> = (props) => (
        <div>{props.age}</div>
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search