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.
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 welcomeMessage
component 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;
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.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.
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.
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.
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.
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.
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.
state
, create class based components.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