To use React FC on functions

Viewed 3253

I want to learn how to use React.FC<> in normal functions on react.js.

I know there are two type of functions; the first is (the one that I prefer):

  function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }

The other one is something like this:

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      "& > * + *": {
        marginLeft: theme.spacing(2),
      },
    },
  })
);

I have been told that if I want to use React.FC<> on functions I should do it like this :

const QuestionCard: React.FC<Props>  = () => (
     <div>Question Card</div>
);

export default QuestionCard;

But I don't want to do it with const functions (if that is how it's called). I want to do it with the normal function. I have tried it like this:

export default function QuestionCard : React.FC<Props>() {

  //duda
  return <div>Question Card</div>;
}

But the code editor shows me an error like this: error image

1 Answers

In typescript you can't apply a type alias to a function statement. You are limited to typing the arguments and return type separately.

function foo(arg1: Arg1Type, arg2: Arg2Type): MyReturnType {
  //...
}

But if you have a function type alias, you must use this form instead:

type MyFn = (arg1: Arg1Type, arg2: Arg2Type) => MyReturnType
const foo: MyFn = (arg1, arg2) => {
  //...
}

That's just the way to the syntax works. What all that means is that if you want to use the React.FC<Props> type alias for your functional component, then you must use the const MyComponent: React.FC<Props>


However, (Warning: this drifts into opinion from here on) I want to add that you don't really need the React.FC at all. All it really gives you an extra children?: React.ReactNode prop, which don't want on every component anyway. In fact, if a component does not allow children, and you pass some to it anyway, then I would expect a type error. React.FC doesn't make it easy to be explicit about that.

For example:

interface Props {
  foo: string
}

// A React.FC declared component that should not take children.
const MyComponentC: React.FC<Props> = ({ foo }) => {
  return <>{ foo }</>
}
const c = <MyComponentC foo='bar' /> // expected usage
const cWithChildren = <MyComponentC foo='bar'>some children</MyComponentC> // no type error

That component is not explicitly typed to accept children, and yet it does. It would be nice if there was a type error.

Instead, lets look at two examples that don't use React.FC and instead declare children explicity.

// A function statement declared component that takes no children.
function MyComponentA({ foo }: Props) {
  return <>Foo: {foo}</>
}
const a = <MyComponentA foo='bar' />
const aWithChildren = <MyComponentA foo='bar'>some children</MyComponentA> // type error


// A function statement declared component that DOES take children.
function MyComponentB({ foo, children }: PropsWithChildren) {
  return <>
    <p>Foo: {foo}</p>
    <p>{children}</p>
  </>
}
const b = <MyComponentB foo='bar' /> // type error
const bWithChildren = <MyComponentB foo='bar'>some children</MyComponentB>

Now the presence of children is enforced by the type system, and the syntax for declaring the component is clean and simple in all cases.

For these reasons, I wouldn't really recommend using React.FC these days.

Typescript playground with above example

Related