As functional React components is more modern with support to hooks which is useful, it’s common practice to rewrite the old styled class components to functional components. This article summarizes some common steps and pitfalls for the transformation.
Common Replacements
Definition
From
1 | class (\w+) extends Component \{ |
To
1 | const $1: FC = () => { |
- It’s for situation without
export
andprops
.
From
1 | (export) default class (\w+) extends Component \{ |
To
1 | $1 const $2: FC<$2Props> = () => { |
- As the second captured word,
$2
is the component name. $2Props
should be defined as the name ofprops
interface.
Attributes Prefix
From
1 | this\.(state\.|props\.)? |
To
1 |
- Assume that
props
is destructed uniformly.
Lift Cycle functions
From
1 | componentDidMount() { |
To
1 | useEffect(() => {}, []); |
componentDidUpdate
can also be transformed touseEffect
, with appropriate dependencies.componentWillUnmount
can be transformed to return function of correspondinguseEffect
handler.
State Related Statement
From
1 | state = { |
To
1 | const [data, setData] = useState(); |
From
1 | this.setState({ |
To
1 | setData(data) |
Class Methods
From
1 | ^(\s*)(\w+)\((\w*)\) \{ |
To
1 | $1const $2 = ($3) => { |
- It’s for regular function definition.
$1
is white spaces,$2
is method name,$3
is parameters
From
1 | ^(\s*)((\w+) = (async )?\((\w+(, )?)*\) =>) |
To
1 | $1const $2 |
- It’s for arrow function definition.
$1
is white spaces,$2
is everything from the method name.
Class Getter
From
1 | ^(\s*)(get) (\w+)\(\) |
To
1 | $1const $2\u$3 = () => |
\u
means capitalizing the following captured word.- The invoking of the getter should have
()
after the name. - If the getter is simple, it can be assign directly without function.
Render function
From
1 | render() { |
To
1 | return ( |
Notable Pitfalls
Name Conflict
It’s possible for class component to have the same name as attributes
and props
, such as this.data
and this.props.data
.
With this.data
become data
, and it’s common to destruct props
as const {data} = props
, the name conflict comes.
State Callback
With this.setState
, we can set a callback to be invoked after the state is changed actually, but we have to change this implementation to useEffect
with the changed state as dependency.
Function as State
If the value of a state is a function, you wrap it into an anonymous function or else the hook version of setState
will treat it as a callback.
Actually, in most case, this kind of state is not related to rendering, so perhaps useRef
is more suitable for them.
This article shows some replacement with RegExp, which will make the transformation from class to functional component easier, and some pitfalls that you may encounter during the process for you to pay attention to, but to be sure, there can be more jobs for different scenarios.