DEV Community

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

ReactJS : When to use Class Component Over Function Component?

Jatin on March 04, 2023

We all know that there are two types of components in React. 1. class components 2. function components Before React 16.8, function components we...
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