Understanding React Hooks — Part 1
ReactJS released a major feature in its 16.8 version, where the functional component will act more like a class component. If you are worried about not able to use the component state or life cycle methods in the functional components, now you can do it with react hooks.
The goal of react hooks is to cover all use cases for classes as soon as possible, however, there are no hooks that are equivalent to the uncommon getSnapshotBeforeUpdate
, getDerivedStateFromError
and componentDidCatch
lifecycles yet, but maybe in future releases?
Few FAQs before we dive deep into various react hooks.
Q. Which versions of React include Hooks?
A. Starting with 16.8.0, React includes a stable implementation of React Hooks.
Q. Do hooks cover all use cases for classes?
A. It does not, as mentioned in the above paragraph, there are no Hook equivalents to the uncommon getSnapshotBeforeUpdate
, getDerivedStateFromError
and componentDidCatch
lifecycles yet, it may be there in future releases.
Q. How can I fetch data using Hooks?
A. useEffect
can be used to get a class components life cycle effects, this would be covered in a moment.
Q. Do I need to rewrite all of my class components?
A. No, Class components will still be around and we should start using hooks for all new components in the project.
Let’s learn some react hooks and get hooked up with these interesting concepts, and see how we can use them.
We will discuss useState
, useEffect
and useRef
in this article and eventually learn many other hooks in future articles.
Let’s get started…
useState
As the name suggests, it will allow you to maintain a local state of functional components.
Syntax,
const [stateVariableOrObject, updateStateFn] = useState(initailState);
Usage:
import React, { useState } from 'react';
const [name, updateName] = useState('medium');
In the above example name
is a state variable, updateName
is a function that will update the value. Whenever there is an update the component will render to display the updated state and useState
is a react hook. Also,useState
with a string medium
is an initial value of the state variable name
.
You can also create state objects. Here is an example,
const [state, updateState] = useState({name: 'medium', state: 'AZ'});
then use the state variable something like this const { name } = this.state;
A code example.
As shown in the above example, name
will have medium
as its initial value and once the button is clicked it will call updateName
function and gets a new value Name Updated
Note:
- You can use multiple
useState
react hook in a component, if required. The same effect can essentially be achieved by using a state object rather than a single state variable. However, using multipleuseState
will not let you consider other state properties within the state object.
2. useEffect
We saw how to use useState
and maintain functional component’s local state, but what about the life cycle hooks like class components has? How can we perform side-effects when components mount or update? And that’s where the useEffect
come into the picture. The useEffect
hook helps us to perform an action each time a functional component renders.
Usage:
import React, { useEffect } from 'react';useEffect(() => {
. . .
});
- When you want to perform an action each time component renders
In the example above on the console Hey there !!!
will be logged each time you click on update
button, which means whenever a state changes, components re-render and the useEffect
will be triggered.
- When you want to perform an action on component update
useEffect
accepts the second parameter, and this will help achieve the component update life cycle to run a particular action only when a particular state updates.
In the above code example, the console log Only trigger on name update
happens only twice, once when the component renders with the value hello
and again when you click on the Update
button since the value of name
now will be world
, if we keep on clicking on the update
button, the count
state variable increases however useEffect
will not trigger every time.
- When you want to perform an action only on the component mount
To trigger useEffect
in the component mount, just pass the second parameter as an empty array []
. Since there is no state mentioned, this will be triggered when the component renders.
- When you want to perform an action only on a component unmount
If you want to clean up a component, you can do so by writing a return () => {}
function within a useEffect
function, this return statement will act as a cleanup. Whenever a useEffect
is triggered, it will run the return function first to see if there is a clean-up required and then the steps outside the return function.
In the example above, unMount
will be logged first, and then onMount
when you click on update
button. You can use this clean-up to clear any event listener, if there are any, or to unsubscribe any subscriptions.
3. useRef
As the name suggests useRef
can be used to refer or to access child HTML components/DOM elements. useRef
returns a mutable ref object whose .current
property is initialized to the passed initialValue
. The returned object will persist for the complete lifetime of the component and does not re-render the component upon change.
Usage:
import React, { useRef } from 'react';export const ComponentUseRef() {
const inputRef = useRef(null);return <>
<input ref={inputRef}/>
</>
}
Few good use case of useRef
includes to focus on an HTML Elements or to count a number of renders that happened in a component.
Let’s see both examples to understand them better.
- To focus on an input element
In the above example, the input element is referred by using useRef
, here inputref.current
refers to the <input/>
element. So whenever the Focus the input
button is clicked, it will call onButtonClick
function which focuses on the input field.
- To log, the number of renders that happens in a component.
Let’s try to use all the hooks we have learned so far, useState
to hold the input value and to update the same, useEffect
to update the render count, and useRef
instantiate the renderCount
the value that persists for the full lifetime of the component.
In the above code example, whenever the name
state value updates, it renders the components, and thus increasing the renderCount
value, there can be a question/confusion here, why should we use useRef
right? We could have just used renderCount
has another state variable? ?But the problem with that is, it will cause an infinite loop since we update the name which indeed updates the renderCount
, and that will render the component again, an important point to note here is useRef
does not cause to re-render the components.
One more importance of useRef
is to store/get a prevProps or prevState.
Check out some examples in GitHub
In the upcoming articles, We will see some example and learn about useReducer
,useMemo
and useCallback
Reference
Learn more about me here,