Hey 👋 new reader,
Pluralsight gave me some free1 month
, get them before
subscriptions
they are gone!
Should you use React.FC for typing React Components
20 May 2020 · 6 mins read Edit PostTypescript provides some interfaces to help with writing React components. React.FC
is one of those interfaces that is used in a lot of apps to define a functional component. The question you should ask yourself is: should you use React.FC
for Typescript react components?
React.FC
This example shows how you can use React.FC
in practice:
import React from 'react'
import { T } from '@example/i18n'
const Header: React.FC = () => {
return <header>{T`Harry's header`}</header>
}
and without React.FC
:
import React from 'react'
import { T } from '@example/i18n'
const Header = () => {
return <header>{T`Harry's header`}</header>
}
- wondering what the
T
is about?
With React component props, use:
const Header: React.FC<{ loading: boolean }> = ({ loading }) => {
if (loading) {
return <header>{T`Loading...`}</header>
}
return <header>{T`Harry's header`}</header>
}
without
const Header = ({ loading }: { loading: boolean }) => {
if (loading) {
return <header>{T`Loading...`}</header>
}
return <header>{T`Harry's header`}</header>
}
Pros of React.FC
1. Helps with Component props
React components have by default 4 props, e.g. Header.displayName
.
// Simple version of the actual interface
interface FC<P = {}> {
(props: P): ReactNode
propTypes?: P
defaultProps?: P
contextTypes?: any
displayName?: string
}
With React.FC
interface I get typings for these props, otherwise we get this type error:
Property 'displayName' does not exist on
type '() => Element'.ts(2339)
2. Gives access to typed children
const Header: React.FC<{ loading: boolean }> = ({ loading, children }) => {
if (loading) {
return <header>{T`Loading...`}</header>
}
return <header>{children}</header>
}
without
// Type error: Property 'children' does not exist on type '{ loading: boolean; }'. ts(2339)
const Header = ({ loading, children } : { loading: boolean }) => {
if (loading) {
return undefined
}
return <header>{children}</header>
}
to fix this, we need to specify the children
prop manually
const Header = ({ loading, children } : { loading: boolean; children: React.ReactNode }) => {
if (loading) {
return undefined
}
return <header>{children}</header>
}
Cons of React.FC
1. Doesn’t help with returning undefined
You cannot return undefined
from a React component, and even with the React.FC
type, the compiler will only tell you at runtime.
Runtime error:
Header(...): Nothing was returned from render.
This usually means a return statement is missing.
Or, to render nothing, return null.
2. Provides access to props.children
when you may not want it
With React.FC
I can put children under my component and they won’t render but will be typed correctly.
const Header: React.FC = () => {
return <header>{T`Harry's header`}</header>
}
export const Example = () => {
return (
<Header>
<p>{T`Children`}</p>
</Header>
)
}
Without this type I get a error instantly
const Header = () => {
return <header>{T`Harry's header`}</header>
}
export const Example = () => {
// Type error: Property 'children' does not exist on
// type 'IntrinsicAttributes & { loading: any; }'. ts(2322)
return (
<Header>
<p>{T`Children`}</p>
</Header>
)
}
3. Difficulty creating a Sub.Component pattern
It is very difficult to create the typical Component and Component.SubComponent pattern (without adding lots of additional workarounds) with React.FC
.
e.g. without React.FC
, to create this:
<Header>
<Header.Item name={T`Login`} />
</Header>
the types are simply
const Header = ({ children }) => <header>{children}</header>
Header.Item = ({ name }) => <p>{name}</p>
Overall
React.FC
is useful for beginners getting into typed React components as it guides you with types. But due to unnecessary addition of children, that you normally do not need, you should stay away and simply type like a normal Typescript function.
More reading
Suggested
- 7 Best Practices for Cypress — 17 April 2020
I recently refactored and improved a large test suite library that used Cypress as the main test automation tool. Here are some best practices and common mistakes I found for working with this library.
- Learn Frontend in 2021 — 21 December 2020
Frontend engineer changes every year. Different technologies, libraries and techniques. This series is everything you need to know to get up to scratch with Frontend Engineering in 2021.