Deciding between Class and Functional Components
In the midst of creating my first React project, I find myself continually facing the same decision with each UI feature I build out — should I make this a class component or functional component? My default up until this point has been the class component, should I need to create a state or implement a lifecycle method along the way, but I keep wondering, shouldn’t I be more intentional with this decision? Of course that question was rhetorical, so I wanted to dig deeper to understand the when and why of choosing a functional over class component, or vice versa.
I mostly default to class components in the event I want to add state at some point. However, due to my new understanding, this mentality is slightly flawed, since functional components can actually also be stateful. Until recently, defining and handling state was only possible in a class component, but with React 16.8 and the introduction of React Hooks (and in particular the useState Hook), functional components can now handle state as well.
Defined in the array, count and setCount can be thought of as the state and the setter (the function that will change the state). The useState hook takes an argument of an initial state that will change on every click event.
So, what about lifecycle methods, the other main usage / rationale I had for implementing a class component over a functional one? Hooks also make lifecycle possible as well. The main lifecycle method I have been using thus far is componentDidMount to handle fetching from my Rails API. In a functional component, we would use the useEffect Hook to replace that method and handle timing of rendering.
The function passed to the useEffect hook is our effect, and each time React renders this component, it will remember and run our effect after updating the DOM.
useEffect Hook will also apply to componentDidUpdate and componentWillUnmount, however note a significant difference between useEffect and componentDidUpdate and componentDidMount — effects run through useEffect will not stop the browser from updating the screen, and will not happen synchronously.
So then, since both of my scenarios for using a class component over a functional component have been debunked as both can handle state and lifecycle methods, how do we know when to use one over the other?
It’s not always black and white, but here are some quick go-to recommendations/suggestions gleaned from various react resources:
- Try to use stateless functions, or functional components, whenever possible
- Go with functional components and hooks when your component only needs to accept props and render JSX
- Go for class component when data fetching, as data fetching with useEffect hooks is not as natural as it is with lifecycle methods.