DEV Community

Cover image for 6 ways to write a React component (TS Included)
Mateo Garcia
Mateo Garcia

Posted on

6 ways to write a React component (TS Included)

Hello everyone, my name is Mateo and like many of you, I have set some goals now that a new year has begun. Sharing, documenting, and applying my knowledge are some of them so I have decided to open this space called Coding with Mateo.

Alt Text

The first post I will write is a compilation of different ways you can write a React component. Additionally, I will leave its version in Typescript in case it is useful to clarify how to annotate the functions in its different presentations, let's start.

React has gradually become the paradigm/technology we think of when it comes to frontend development. Watch some videos, buy some Udemy courses, make your first task list, finally master the main concepts. However, the diversity of syntax provided by Javascript makes that at some point we don't understand why some people write components one way and others another way.

It is important to remember that:

  • A React component is a function that thanks to the composition can contain internal functions, including new components.

  • Javascript functions are objects with the difference that they can be executed through parentheses.

  • Even if you are still maintaining/writing class components, those components are interpreted, transposed, and executed as ES5 functions since those classes are only syntactic sugar of recent EcmaScript features.

Whether you are working on a project by yourself or in a team, defining a syntax to declare your utility functions and React components can help to simplify the fatigue caused by the rapid growth of the project structure.

Below, I show you different ways to write a React component using a button as an example.

1.Using a regular function.

   // Button.jsx
   function Button (props) {
      return <button>{props.children}</button>
   }

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   function Button (props: ButtonProps) {
      return <button>{props.children}</button>
   }
Enter fullscreen mode Exit fullscreen mode

2.Using a function expression.

   // Button.jsx
   const Button = function (props) {
      return <button>{props.children}</button>
   }

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   const Button = function (props: ButtonProps) {
      return <button>{props.children}</button>
   }

Enter fullscreen mode Exit fullscreen mode

3.Using an arrow function with const.

   // Button.jsx
   const Button = (props) => {
      return <button>{props.children}</button>
   }

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   const Button = (props: ButtonProps) => {
      return <button>{props.children}</button>
   }
Enter fullscreen mode Exit fullscreen mode

4.Using an arrow function with let.

   // Button.jsx
   let Button = (props) => {
       return <button>{props.children}</button>
   }

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   let Button = (props: ButtonProps) => {
       return <button>{props.children}</button>
   }

Enter fullscreen mode Exit fullscreen mode

5.Using an explicit return

   // Button.jsx
   let Button = (props) => <button>{props.children}</button>
   // or
   const Button = (props) => <button>{props.children}</button>

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   let Button = (props: ButtonProps) => <button>{props.children}</button>
Enter fullscreen mode Exit fullscreen mode

6.Using a class.

    // Button.jsx
    class Button extends React.Component {
      render () {
         return <button>{this.props.children}</button>
      }  
    }

   // Button.tsx
   type ButtonProps = {
      children: React.ReactNode;
   };

   class Button extends React.Component<ButtonProps> {
      render() {
         return <button>{this.props.children}</button>;
      }
   }

Enter fullscreen mode Exit fullscreen mode

Finally, I must say that, all the ways of writing them work well. There is no one better than another, feel free to use the one you like best.

However, I would like to clarify that:

  • The class components are being progressively deprecated.

  • Declaring components with a let can be useful when performing conditional rendering based on the props of a parent component.

   function ThisOrThat (props) {
      /* 
        Maybe some difficult logic.     
        Of course, that code does not smell good, however, it's 
        important to know that's possible to do this.
      */
      let renderedComponent = getComplexComponent(props); // 
      if (!renderedComponent) {
         renderedComponent = <FallbackComponent />
      }
      return <section>{renderedComponent}</section>
   }
Enter fullscreen mode Exit fullscreen mode

I would love to know your opinion and what topics you would like to see in my blog posts. Also if you can react to this blog that would make me very happy.

Thank you very much and happy new year 🎉🥳

Top comments (6)

Collapse
 
belinde profile image
Franco Traversaro • Edited

In typescript it's way more concise using the React.FC type:

const Button: React.FC = (props) => {
      return <button>{props.children}</button>
}
Enter fullscreen mode Exit fullscreen mode

It will check also the return type of the component, so if you're using some weird conditional return you'll be sure to return always a valid component.

It's a generic, so you can add the types of your props without caring of React's stuff:

type ButtonProps = {
   onClick: () => void
}
const Button: React.FC<ButtonProps> = ({children, onClick}) => (
   <button onclick={onClick}>{children}</button>
);
Enter fullscreen mode Exit fullscreen mode

Destructuring props is also a good way to KISS, and all the types are correctly inferred.

Collapse
 
lukemorales profile image
Luke Morales

There's a lot of discussion on the use of React.FC around the internet for various reasons, I don't think there's a right or wrong answer, but I rather not use React.FC as it breaks defaultProps and it accepts children being passed for every component (and that's not the behaviour you want for every component).

I rather type props the way the article presents or with the PropsWithChildren generic provided by React.

Just giving another insight to the discussion!

Collapse
 
mateo_garcia profile image
Mateo Garcia

Thank you both of you guys, as you said, we can use ReactFC or PropsWithChildren types. I forgot to annotate the component's output. However, I avoided props de-structuring on purpose just to make the functions more readable. Really cool feedback 🤓

Collapse
 
serkhioo profile image
Serkhio⚡🇨🇴 • Edited

Nice job!

Collapse
 
clamstew profile image
Clay Stewart • Edited

Couldn’t the first five be summed up with “different ways to write a function with progressively terse es6+ conventions”?

So then it’s FC vs CC.

Collapse
 
mateo_garcia profile image
Mateo Garcia

Of course, we could. It's a good way to group them ✌🏼