dontexist
dontexist

Reputation: 5652

What is the TypeScript return type of a React stateless component?

What would the return type be here?

const Foo
  : () => // ???
  = () => (
    <div>
      Foobar
    </div>
  )

Upvotes: 92

Views: 161977

Answers (8)

Tushar Nain
Tushar Nain

Reputation: 1

import "./App.css";

function App(): React.ReactElement {
  return <>hello</>;
}

export default App;

Use this in the react functional component.

Upvotes: 0

deepyes02
deepyes02

Reputation: 178

Or for traditional functions, maybe this ???

import { ReactElement } from "react";

export default function Home () : ReactElement<React.FC> {
    return (
        <>
            Hello world
        </>
    )
}

Upvotes: 1

Timo
Timo

Reputation: 2997

StatelessComponent type mentioned in this answer has been deprecated because after introducing the Hooks API they are not always stateless.

A function component is of type React.FunctionComponent and it has an alias React.FC to keep things nice and short.

It has one required property, a function, which will return a ReactElement or null. It has a few optional properties, such as propTypes, contextTypes, defaultProps and displayName.

Here's an example:

const MyFunctionComponent: React.FC = (): ReactElement => {
  return <div>Hello, I am a function component</div>
}

And here are the types from @types/react 16.8.24:

type FC<P = {}> = FunctionComponent<P>;

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

Upvotes: 148

Freewalker
Freewalker

Reputation: 7355

If using the function keyword, the best return type appears to be JSX.Element | null.

For now our team is using JSXNode as shorthand, since these are the only two types that can be returned directly as a JSX result:

type JSXNode = JSX.Element | null;

Edit: looks like eventually React.ReactNode is the intended return type for JSX but it's currently not possible. (Reference)


Background:

None of the answers here seem to address the most common modern case - that you have a function returning an element. What type should this return?

function MyComponent(): SomeTypeHere {
  return <>...</>;
}

The recommended way to hide the component is to return null, so it's not clear what clean return type that would be. Typing JSX.Element | null everywhere or even making a custom type like that seems it should be unnecessary given how universal this case is. ReactNode also doesn't work because undefined can't be returned as JSX.

Overall the best return type seems to be JSX.Element | null. That is the return type of the FC type which is used if you're not using the function keyword:

const MyComponent: FC = () => { <>...</> }

Upvotes: 8

Vishal Sakaria
Vishal Sakaria

Reputation: 1397

interface ISomeCoolInterface {
   some: 'string';
   cool: 'string';
   props: 'string' 
}    

const SomeCoolComponent
    : React.FC<ISomeCoolInterface> 
    = ({ some, cool, props }): JSX.Element => {
        return <SomeCoolComponent>{some, cool, props}</SomeCoolComponent>      
    }

The important bit here being the return type JSX.Element

Upvotes: 18

Hassen
Hassen

Reputation: 7664

I would also add .SFC, which stands for Stateless Functional Component.

const Foo
  : React.SFC<{}>
  = () => (
    <div>
      Foobar
    </div>
  )

Upvotes: 1

dontexist
dontexist

Reputation: 5652

The correct return type here is ReactElement<P>, but a better option would be to use React.StatelessComponent<P> like this

const Foo
  : React.StatelessComponent<{}>
  = () => (
    <div>
      Foobar
    </div>
  )

Upvotes: 7

Ruan Mendes
Ruan Mendes

Reputation: 92324

See https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts

Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children).

function createElement<P extends DOMAttributes<T>, T extends Element>(
    type: string,
    props?: ClassAttributes<T> & P,
    ...children: ReactNode[]): DOMElement<P, T>;

So it's DOMElement<P, T>

Upvotes: 1

Related Questions