DEV Community

Chanvin Xiao
Chanvin Xiao

Posted on • Originally published at chanvinxiao.com

Transform Class React Components to Functional

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

class (\w+) extends Component \{
Enter fullscreen mode Exit fullscreen mode

To

const $1: FC = () => {
Enter fullscreen mode Exit fullscreen mode
  • It's for situation without export and props.

From

(export) default class (\w+) extends Component \{
Enter fullscreen mode Exit fullscreen mode

To

$1 const $2: FC<$2Props> = () => {
Enter fullscreen mode Exit fullscreen mode
  • As the second captured word, $2 is the component name.
  • $2Props should be defined as the name of props interface.

Attributes Prefix

From

this\.(state\.|props\.)?
Enter fullscreen mode Exit fullscreen mode

To


Enter fullscreen mode Exit fullscreen mode
  • Assume that props is destructed uniformly.

Lift Cycle functions

From

componentDidMount() { 
Enter fullscreen mode Exit fullscreen mode

To

useEffect(() => {}, []);
Enter fullscreen mode Exit fullscreen mode
  • componentDidUpdate can also be transformed to useEffect, with appropriate dependencies.
  • componentWillUnmount can be transformed to return function of corresponding useEffect handler.

State Related Statement

From

state = {
  data: null,
};
Enter fullscreen mode Exit fullscreen mode

To

const [data, setData] = useState();
Enter fullscreen mode Exit fullscreen mode

From

this.setState({
  data,
});
Enter fullscreen mode Exit fullscreen mode

To

setData(data)
Enter fullscreen mode Exit fullscreen mode

Class Methods

From

^(\s*)(\w+)\((\w*)\) \{
Enter fullscreen mode Exit fullscreen mode

To

$1const $2 = ($3) => {
Enter fullscreen mode Exit fullscreen mode
  • It's for regular function definition.
  • $1 is white spaces, $2 is method name, $3 is parameters

From

^(\s*)((\w+) = (async )?\((\w+(, )?)*\) =>)
Enter fullscreen mode Exit fullscreen mode

To

$1const $2
Enter fullscreen mode Exit fullscreen mode
  • It's for arrow function definition.
  • $1 is white spaces, $2 is everything from the method name.

Class Getter

From

^(\s*)(get) (\w+)\(\)
Enter fullscreen mode Exit fullscreen mode

To

$1const $2\u$3 = () =>
Enter fullscreen mode Exit fullscreen mode
  • \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

render() {
  return (
    <></>
  );
}
Enter fullscreen mode Exit fullscreen mode

To

return (
  <></>
);
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)