paint-brush
Understanding Functional Componentsby@nkgokul
10,921 reads
10,921 reads

Understanding Functional Components

by Gokul N KAugust 31st, 2018
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

React is all about keeping your front-end code modular and reusable. Components play a crucial role in making React modular. <strong>Components are the building blocks of React.</strong> Using the right kind of components can make sure that your front end code is reusable and scalable.

Company Mentioned

Mention Thumbnail
featured image - Understanding Functional Components
Gokul N K HackerNoon profile picture

React is all about keeping your front-end code modular and reusable. Components play a crucial role in making React modular. Components are the building blocks of React. Using the right kind of components can make sure that your front end code is reusable and scalable.

There are two types of components in react functional and class based components. Using the right type of component will make a lot of difference to your codes’ reusability and performance.

In this article we will explore what are the differences between functional components and class based components, advantages and disadvantages of these two types of components and thumb rules to decide when to use what.

What are functional components?

Let us say we need to create a component for printing the welcome message. Let us create a component called welcomeMessage In its simplest form the component would like following



const welcomeMessage = () => {return "Hello there"};

export default welcomeMessage;

This code can be easily read and understood by any Javascript developer, even one without any background in React. It is just a harmless, easily readable function. You have a function definition and then the function is being exported. That is all you need to have in the file that contains a component. Everything else is optional. You should observe that we are not even having import React from "react"; which is a common sight in React. This is because we are just returning some text from this function. If you are using JSX you will need to import React class.

While this will qualify as a React component, in most of our scenarios we will generally be returning some JSX, based on the props received by our component. It is this ability to create expected output based on the input props which makes components reusable. So let us modify our welcomeMessage to take props as input and output the welcome message based on that.

import React from "react";







const welcomeMessage = props => {return (<div><p>Hello <b>{props.name}</b> from welcomeMessage</p></div>);};

export default welcomeMessage;

As you can see this is just a pure function that takes props as the input and returns JSX as the output based on the input.

We are using the ES6 standard in the above example. The same code can also be written as following.







function welcomeMessage(props) {return (<div><p>Hello <b>{props.name}</b> from welcomeMessage</p></div>);};

But I wouldn’t suggest using this format. React uses of ES6 for a reason and hence it makes sense that we also stick to the same. It is better to align ourselves to the future direction of the language. Thanks to babel setup in Create React App(CRA) the backward compatibility of our code is taken by the default setup. As an added advantage your code will blend in well with React code when you use ES6.

Now we can pass the props to our welcomeMessagecomponent within the App.js in the following manner.



import React, { Component } from "react";import logo from "./logo.svg";import "./App.css";

import welcomeMessage from "./components/WelcomeMessage";











class App extends Component {render() {let numberName = 5;return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><h1 className="App-title">Welcome to React</h1></header><p className="App-intro">**<**WelcomeMessage name="React enthusiast"/>

    </p>  
  </div>  
);  


}}

export default App;

Advantages of functional components

  1. They help keep your code simple, readable and reusable.
  2. Since they are pure functions it is easier to test them.
  3. Since they do not have access to state you are forced to think in terms of passing props which will make your components reusable. If you think your component can be used outside of your project you can even consider publishing your component to npm.

Should I stick to functional components

So does that mean it is always better to use functional components? Not really. But they are always a great starting point for your components. If you really feel the need, you can convert them to class based components. In the next part we will explore when it makes sense to use class based components and what are the advantages of using them.

What are class based components?

A class based component is a JavaScript class that extends React.Component The only required method in React.Component is the render method.

So our functional component helloUserFunctionalComponent which was like the following


//functional Componentimport React from "react";







const WelcomeMessage = props => {return (<div><p>Hello <b>{props.name}</b> from WelcomeMessage</p></div>);};

export default WelcomeMessage;

would now become like this.

import React, { Component } from "react";









class WelcomeMessage extends Component {render() {return (<div><p>Hello {this.props.name} from WelcomeMessage.</p></div>);}}

export default WelcomeMessage;

As mentioned earlier functional components make a great starting point. I generally start out with functional components and then switch to class based components only in one of the following scenarios.

Need to make use of state

There will be some scenarios where you need to keep track of the state of your component . In such scenarios it is better to make use of the state. An example can be accordion where you need to maintain whether the accordion is clicked or not in state. This corresponds to the state of the UI component. There is one more scenarios where we use state to save external data which we will discuss next.

Need to fetch data

Another scenarios is where you need to fetch data. In such scenarios it is again better to use class based components. Instead of using a single class based component for both fetching data and rendering data, it is better to use an approach called containers. In a container you generally do the data fetching and store the fetched data in state. Then you pass the relevant data from state to a functional component as props , which will just render the data provided. The components that just take data as props and render them can be considered similar to the templates. They are also called dumb components.

Need some lifecycle hooks.

Class based components provide various lifecycle hooks which allow us to hook into various stages of component lifecycle and perform actions based on that. While there are many lifecycle hooks, componentDidMount will be the most frequently used one. For example in the previous section we discussed about data fetching, which generally happens in the componentDidMount() hook. Let us look at the code for a scenario where we need to fetch data from an API and then render it.

We will use a container to do the API call and then we will use dump component to do the rendering.

Container — A special purpose class based component.










class UserListContainer extends React.Component {state = { users: [] };componentDidMount() {let users = await fetchUsers();this.setState({ users: users });}render() {return <UserList users={this.state.users} />;}}

A dumb component for rendering our user list.






const UserList = props =><ul>{props.users.map(user => (<li><a href="{user.profile_link}">{user.name}</a></li>))}</ul>

As you can see since we created a separate UserList functional component, we can reuse it to render a Userlist from any source as long as the passed users prop has profile_link and name attributes in the user object.

Need performance optimisations provided by Component based class

If you have worked on the front end optimisation you would have observed once the page is loaded and the state changes most of the time in front end is spent in re-rendering the components. Time taken for javascript processing seems to be negligible when compared to the render times. Making sure that you only re-render components when required can greatly improve the performance of your front end app.

Class based components have an optional method calledshouldComponentUpdate which decides whether you need to re-render a component or not. This method takes nextProps and nextState as inputs using which you can return a boolean . If true is returned it means component will re-render and if a false is returned it means there is no need to re-render the component. If you meddle with this function without understanding the consequences you might end up with more issues than what you began with. There is also an easier alternative. React provides React.PureComponent. In most of the scenarios it would suffice to extend React.PureComponent instead of React.Component . It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state.

Summary

  1. As a rule of thumb start with functional components and transition to class based components only when you see the need.
  2. Since functional components do not have access to state it prevents you from over using the state unnecessarily. Making use of state can make you lazy. Starting with a functional component makes you think if you really need to use state.
  3. Functional components keep your code simple, readable and reusable.
  4. Functional components are easy to test.
  5. Whenever you should make use of state, create class based components.
  6. Use class based components whenever you want to use performance optimisations provided by Component base class.
  7. Separate data fetching and rendering. Or in other terms keep your business logic/context separate from presentation.
  8. For data fetching use container pattern as it will help you follow the paradigm of separation of concerns. Containers are used for data fetching and in turn use other components for rendering.
  9. I remember reading somewhere “Don’t over burden your components with application logic or context specific details”. That is a good base rule and everything else stems from it.

I wrote this post as a sample for Mosh. You can checkout his website on https://programmingwithmosh.com/ and he also has a course on React which you can check out on https://codewithmosh.com/p/mastering-react

You may also like the following articles.


Understanding promises in JavaScript_I have had a kind of “love and hate” relationship with JavaScript. But nevertheless JavaScript was always intriguing…_hackernoon.com


Understanding async-await in Javascript_Async and Await are extensions of promises. So if you are not clear about the basics of promises please get comfortable…_hackernoon.com


Should I use Promises or Async-Await_I recently read a medium post where the author claimed that using async-await is better than using promises. While this…_hackernoon.com


Understanding npm in Nodejs_I think npm was one of the reasons for quick adoption of nodejs. As of writing this article there are close 7,00,000…_hackernoon.com