DEV Community

Cover image for ReactJS : When to use Class Component Over Function Component?
Jatin
Jatin

Posted on

ReactJS : When to use Class Component Over Function Component?

We all know that there are two types of components in React.

1. class components
2. function components

Before React 16.8, function components were stateless.
However, with the introduction of hooks in React 16.8,Function components became capable of having state and lifecycle methods (here I am referring to lifecycle methods using hooks).

The ability to share stateful logic independent of UI rendering logic made function components popular among React developers. With function components, we can do almost everything possible with class components.

Then why does ReactJS still have class components?
Despite Having so many useful features in function components, There are some cases in which we need to use the Class component over the Function component:

1. Error boundary

When an error occurs usually it displays a component tree that crashed on screen, it can leave a bad impression on the end-user.

Error boundaries help us deal with this situation.
Error boundaries allow us to display fallback UI when an error occurs inside a component.

We can use error boundaries to trace client-side errors and provide useful information for debugging.
It's not possible to create an error boundary with a function component.

Error boundaries can only be implemented with class components.

2. Pure Component

Many times, we need to avoid unnecessary re-rendering of components depending on certain criteria.

In such cases, We can use pure components by extending React.PureComponent, as they have a static method "shouldComponentUpdate" that decides whether to re-render or not based on the component's props and state.

Many times react js developers use the "useMemo" hook to avoid unnecessary re-rendering like this :


   const App=()=>{

                return useMemo(()=>{
                    return <>{/*Code*/}</>
                  },[dependancies])
              }

Enter fullscreen mode Exit fullscreen mode

However, everything before the "useMemo" hook will still be executed when the component updates its state. Therefore, "useMemo" may not always be the best option for avoiding unnecessary re-rendering.

Since we cannot create pure components with function components, we will need to use class components.

3. Life Cycle methods

I know This should not be the case, because most lifecycle methods like componentDidMount, componentDidUpdate, or componentWillUnmount can be replaced with useEffect.

It is important to note that the useEffect hook requires some extra care when it comes to dependencies and avoiding infinite loops.

One has to be very careful about dependency. and make sure dependency is not updated from inside the hook (this can lead to an infinite loop)

In a class component, the lifecycle methods are executed automatically when certain events occur, such as when the component is mounted, updated, or unmounted.

Top comments (22)

Collapse
 
brense profile image
Rense Bakker • Edited
  1. You can use error boudaries with functional components: react-error-boundary
  2. Pure components were an abomination that caused people to put way to much logic in parent components, just to be able to claim the children were pure.
  3. Why do you want to use lifecycle methods? They don't allow you to do anything that you can't also do with hooks, but in a more concice way with more concicely named custom hooks resulting in much cleaner code.

Then why does ReactJS still have class components?

Because they want to maintain backwards compatibility and they are still working on updating the docs (see the beta docs)

Collapse
 
imparmarjatin profile image
Jatin • Edited

@brense Just FYI

  • react-error-boundary package itself uses class component Image description
  • pure components are used for avoiding unnecessary re-rendering
  • using a life cycle method or not is up to the developer, i have shared , what can go wrong if developer takes things lightly
Collapse
 
brense profile image
Rense Bakker
  1. In your article you said that you cannot use error boundaries with functional components, you can. What happens under the hood doesn't make this any less true: Wanting to use error boundaries is NOT a reason to go for class-based components, because you can infact use error boundaries with functional components.
  2. You avoid unnecessary rerenders by not changing the state of your component. Having pure child components is irrelevant. If the unpure parent keeps rerendering, so will the children. React hooks offers more ways to ensure that the state of your component doesn't change, by using memiozation. To achieve the same effect in class-based components, you have to hack the shouldComponentUpdate method, which is extremely dirty and has historically resulted in many headaches and developers losing the will to live.
  3. Yes there are many pitfalls with certain lifecycle methods, they've historically been used to hack the way that React worked (see 2). This problem isn't completely gone in React hooks, people still find ways hack things with the useEffect hook. It's developer nature I guess... Not taking the time to really understand how things are supposed to work.
Thread Thread
 
imparmarjatin profile image
Jatin

-In my article i said that we cannot create (not use) error boundaries with functional components.
Image description
What happens under the hood clearly make this true.
Wanting to create error boundaries is GOOD a reason to go for class-based components,because we can't in fact create error boundaries with function components.
-As you said "If the unpure parent keeps rerendering, so will the children",and that's the exact case where need to use pure component. Because see memoization(React.memo) will only work for props,and its only make shallow comparison by default.

Thread Thread
 
brense profile image
Rense Bakker

Memoization works for all state. It allows you to only rerender the parent if the state you're interested in has actually changed. This results in less rerenders of parent and children. Pure components can't hold any state, only props. This meant in practice that people would move the state up to the parent component to artificially keep its children "pure". Because there is no momoization in class components this meant that the parent would rerender more frequently because it was controlling more state and any state change would trigger a rerender of the parent and all of it's fake "pure" children. In the modern day, we learned that its better to keep state as low in the tree as possible so it doesn't trigger unnecessary rerenders in the parent.

Thread Thread
 
imparmarjatin profile image
Jatin

"Pure components can't hold any state, only props." Have you confirmed this?
As far i know,React.PureComponent is similar to React.Component (AS per the react doc).So they can have state.But for React.memo as i can read in the doc

Image description

Thread Thread
 
brense profile image
Rense Bakker • Edited

React.memo is not the only memoization technique in React hooks... useMemo and useCallback are the memoization hooks you want to be using.

This is all you need to know about Pure components: deprecated beta.reactjs.org/reference/react/P...

Thread Thread
 
imparmarjatin profile image
Jatin

For useMemo i already said,everything outside callback will be executed when component will be re-rendered.Now the problem with useMemo is that dependencies are compared shallowly (by reference not by value ),
for example if some one pass an array in dependency and at certain stage if reference of array is changed (i.e array being updated by API call but value still remains the same),then useMemo will cause re-render.

For "Pure components: deprecated ",I have read the link you shared, And have you noticed ? They are teaching how to use PureComponent in React.In that link they clearly says "Class components are still supported by React, but we don’t recommend using them in new code".Then why they are teaching how to use PureComponent?? (Please dont say "to maintain backwards compatibility")
When they are not recommend using them in new code??

Thread Thread
 
imparmarjatin profile image
Jatin

And the best part is that they are referring React.memo instead useMemo in that link instead ,even React.memo is not the only memoization technique in React hooks.

Thread Thread
 
brense profile image
Rense Bakker

Everything everywhere in React has always been and always will be shallow compared. This was also the case with React class components unless you wrote your own custom shouldComponentUpdate. All I can tell you is... Don't change the reference to your array if you don't mean to change it... If you do, you want your component to rerender and your useMemo that depends on the array to be executed. This is how React has always worked. If you dont want your component to respond to your array when it changes, you should use the useRef hook.

"Class components are still supported by React, but we don’t recommend using them in new code"

Yes that's what backwards compatibility means... Dont use in new projects, but you can upgrade your old projects to new react version, without breaking your old class components.

Thread Thread
 
brense profile image
Rense Bakker

Everything everywhere in React has always been and always will be shallow compared. This was also the case with React class components unless you wrote your own custom shouldComponentUpdate. All I can tell you is... Don't change the reference to your array if you don't mean to change it... If you do, you want your component to rerender and your useMemo that depends on the array to be executed. This is how React has always worked. If you dont want your component to respond to your array when it changes, you should use the useRef hook.

"Class components are still supported by React, but we don’t recommend using them in new code"

Yes that's what backwards compatibility means... Dont use in new projects, but you can upgrade your old projects to new react version, without breaking your old class components.

Thread Thread
 
brense profile image
Rense Bakker

Yes React.memo is what people tend to use instead of pure components. React.memo and useMemo are not the same thing though. useMemo affects the state of your component while React.memo just memoizes your component similarly to how useCallback works for callbacks inside your component.

Thread Thread
 
imparmarjatin profile image
Jatin • Edited

"This was also the case with React class components unless you wrote your own custom shouldComponentUpdate."
-And that's the case we need class component.

"All I can tell you is... Don't change the reference to your array if you don't mean to change it".
-Is it even possible?

Thread Thread
 
brense profile image
Rense Bakker

Yes?

let someArray = [1, 2, 3]
someArray = [...someArray]
// Same value, changed reference 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
imparmarjatin profile image
Jatin

Thanks for reading!

Collapse
 
leob profile image
leob

Interesting that there are still edge cases where class based components are needed!

Collapse
 
imparmarjatin profile image
Jatin

Thanks for reading!

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

There are not I think this is an article written a few years ago and published now.

Collapse
 
imparmarjatin profile image
Jatin

Thanks for reading!

Collapse
 
leob profile image
leob

LOL nice, so we're even getting info that's outdated :-P

Thread Thread
 
ivan_jrmc profile image
Ivan Jeremic

Yep seems like it. Don't use class components please🙏

Thread Thread
 
leob profile image
leob

No definitely not ... that's why I was rather surprised by this post :-D