[Question] Should we be using React.FunctionComponentElement type?

8
closed
devinrhode2
devinrhode2
Posted 1 year ago

[Question] Should we be using React.FunctionComponentElement type? #379

I am just trying to figure out what's a good strategy for the return types of functional react components that return jsx. I'm not a fan of everything being typed as JSX.Element. I did find that React.FunctionComponentElement requires some generics to be passed in, which seems like it might be something we want to use, but not sure.

hellatan
hellatan
Created 1 year ago

You should be able to type your function components like this:

import React, { FC } from 'react';

type Props = {
    prop1: string;
    prop2: string;
}

const MyComponent: FC<Props> = ({ prop1, prop2 }) => {
    return (
        <div>{prop1} {prop2}</div>
    )
}

FC is shorthand for FunctionComponent. The Props is the generic value you're passing in.

Is that what you're looking for?

sw-yx
sw-yx
Created 1 year ago

what @hellatan said

devinrhode2
devinrhode2
Created 1 year ago

This is great, that makes perfect sense, it's just FunctionComponent :)

What should be the return type of MyComponent?

And how would we type <MyComponent prop1={'foo'} prop2={'bar'} />? Is it the same as the return type of MyComponent?

const MyComponent: FC<Props> = ({ prop1, prop2 }): JSX_DIV => {
    const JsxDiv: JSX_DIV = <div>{prop1} {prop2}</div>
    return JsxDiv
}

export const SecondLevelComponent: FC<Props> = (): JSX_MYCOMPONENT {
  const myComponentReturn: JSX_MYCOMPONENT = <MyComponent prop1={'foo'} prop2={'bar'} />
  return myComponentReturn
}

What should these JSX_DIV and JSX_MYCOMPONENT types be?

devinrhode2
devinrhode2
Created 1 year ago

I'm thinking JSX_MYCOMPONENT might be some sort of React.FunctionComponentElement, but I'm only a few hours in and this jsx typing stuff feels like a super massive black hole

sw-yx
sw-yx
Created 1 year ago

JSX.Element - try to use the TS playground to make it easier to communicate and help you https://www.typescriptlang.org/play?#9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwCwAUI7hAHarwCyAngMImRWWVjABcmKjAB0AMV4AeZK24A+OAF44ACgDecMMTABGADT7DAJjgBfcUu4BKcQCkAygA0pAUQA2WEMLw6mo6jHDhcCzs8M6oAB4AIsAAbhpw8gAmKSo6BhDG1nC5ltbyAPRZySphEZQwAK5QrHCxiSmM1oyMWHGQsJFsHHCuWFEZADJYyVg+-OBsgeLYeNJyispqmlpOLR7efgEiGiE1UUMgfAILItgNTS57vv6BafI8c4IvecbqOmQEEAgZEK3wsvzIACNkFBgXAytUGOE6o1mhcPtcYLcUR0gA

my advice - you are going down too far this rabbit hole. newbies often try to type every little thing. this makes for intolerable typescript. follow the style of this guide - annotate where necessary and let typescript infer the rest.

hellatan
hellatan
Created 1 year ago

by using FC/FunctionComponent, that type is already returning a ReactElement. You don't need to add an actual return type like you have outlined with FC<Props> = (): JSX_MYCOMPONENT - that is redundant.

That's one great thing (of many!) about TypeScript is that you can create a type that has both the arguments and the return type in one value so you don't always have to declare both with your function. A good example of this are event handlers declared by react. Let's take mouse event handler for example. React has both MouseEvent and MouseEventHandler. They are almost identical except the latter extends from the former.

const handleClick = (event: MouseEvent<HTMLAnchorElement>): void => { ... }

is equivalent to

const handleClick: MouseEventHandler<HTMLAnchorElement> = event => { ... }
stale[bot]
stale[bot]
Created 11 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions!

sw-yx
sw-yx
Created 11 months ago

closing as stale