I've seen two ways of declaring a SFC in React with Typescript, which are these two:
import * as React from 'react'
interface Props {
message: string
}
const Component = (props: Props) => {
const { message } = props
return (
<div>{message}</div>
)
}
export default Component
and:
import * as React from 'react'
interface Props {
message: string
}
const Component: React.StatelessComponent<Props> = props => {
const { message } = props
return (
<div>{message}</div>
)
}
export default Component
From this question I see that with the second way you can omit children from your interface if you are using it in your component.
Are there any more differences? Which one is the preferred one and why?
Looks like React.SFC
and React.StatelessComponent
are deprecated.
Use React.FunctionComponent
instead:
import * as React from 'react'
interface IProps {
text: string
}
export const MyComponent: React.FunctionComponent<IProps> = ({ text }: IProps): JSX.Element =>
<div>{text}</div>
Technically the name doesn't imply the same thing though, as Dan Abramov summed up nicely
EDIT:
Note it's often aliased as React.FC<>
now.
When you declare that const Component: React.StatelessComponent<Props>
You basically declaring what this function gets, and what it returns:
interface StatelessComponent<P> {
(props: P ... ): ReactElement<any>;
So for readability, I would actually do:
const Component = (props: Props): JSX.Element => {
Because here the developer that looks into this code don't need to know what is the interface of StatelessComponent
- he can just read what goes in and what goes out.
And basically, it is all a big:
const Component: React.StatelessComponent<Props> = (props: IProps): JSX.Element =>
The definition for React.StatelessComponent<T>
is:
interface StatelessComponent<P> {
(props: P & { children?: ReactNode }, context?: any): ReactElement<any>;
propTypes?: ValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
In your for snippet Component
is inferred by the compiler to be:
(props: Props): ReactElement<any>
(or something similar).
If you write the first one like this:
const Component = (props: Props & { children?: ReactNode }) => {
...
}
You are pretty much getting the same thing (as long as you don't use the properties of Component)
UPDATE: read the final part for React Hooks update
The preferred one is React.SFC (Before React 16.7):
import * as React from 'react'
interface Props {
message: string
}
const MyComponent: React.SFC<Props> = props => {
const { message } = props
return (
<div>{message}</div>
)
}
export default MyComponent
Why?
SFC stands for Stateless Functional Component.
About your 1st examle, given it was done "manually" it has some problems. For example, it cannot point to props.children, because it wasn't defined in your interface. You don't have this problem with React.SFC.
(Note that Stateless Functional Component, Functional Component and Stateless Component seem to mean the same but actually are 3 different things (Functional Components vs. Stateless Functional Components vs. Stateless Components)
Given you're looking for a Stateless Functional Component, React.SFC is exactly the way to go. Other options may not be functional or may not be stateles, or may not fulfill a correct Component interface (like your manual example).
EDIT: Update since React Hooks arrived:
Since React hooks arrived, function components can also have internal state, so the disctintion is smaller now. The preferred way for function components (state or stateless) now is React.FunctionComponent
const MyComponent: React.FunctionComponent<Props> = props => {
// ... Same as above
}
Cheers, from La Paz, Bolivia.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With