React Hooks was introduced in v16.8 and they have been a life-saver for the React community since then. React Hooks solves some of the important problems:
Hooks makes it easy to reuse stateful logic between components. Though there were other patterns like Higher- Order Components and Render-Props to make components reusable they require restructure of component hierarchy making the code difficult to maintain.
Lifecycle methods of the classes were bloated with unrelated logic and side effects leading to bigger unmanageable components.
Class components were difficult to understand and can easily be misused leading to flaky reloads. React Hooks lets us use most of React features like managing state and lifecycle using a functional component.
React Hooks are nothing but javascript functions that can be used inside functional components or other hooks. Hooks allow you to add state and handle side effects from inside functional components. Name of all the hooks should start with the word “use”. There are some more Rules of Hooks to keep in mind.
At the time of writing this post there are 10 hooks out of which 3 are basic and 7 are additional. Let’s look at each of these hooks with an example for easy understanding.
useState() is one of the most important hooks.
Takes initial state as an argument and returns the current state and a function to update it.
If the value of state depends on previous state you can pass a function which receives previous state as input and returns the latest state.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-app-js
Note in this example there are two states name and quantity which can be managed independently using useState!. This was not possible with class components.
Subscriptions, DOM updates, API calls, data fetching and other side effects can be included in the useEffect() hook.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-useeffectsample-js
There can be a number of useEffect hooks defined in a component.
useEffect is executed every time the component finishes rendering. However it might be overkill to fire the effect for every update hence there is an option to specify dependencies list as the second argument so the effect is only recreated when its dependencies change.
Oftentimes effects create some resources that need to be cleaned up after the component is unmounted, useEffect can return a function which will be executed when the component is removed from UI. If the component is rendered multiple times, the previous effect is cleaned up before the next effect is executed.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-useeffectsample2-js
In this example the previously created timer is cleared before a new timer is created.
Context in React makes it possible to access props in the parent component from the child component. This saves you from the hassle of props drilling. However context could be used only in class components. useContext() lets you read the context and subscribe to its changes from a functional component. Lets build upon our shopping list example where we display the shopping list item added in the App component in the ShoppingList component.
Let’s create the context
We will declare the itemList in our App component and wrap it with to provide the value for this context.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-usecontextsample-js
Now, let’s move onto the ShoppingList Component. useContext() accepts a context object and returns the current context value of that context.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-shoppinglist-js
We have discussed the most important hooks so far. There are some more advanced hooks that help you write clean and efficient code. Here is the list of hooks with brief description of them from documentation.
Custom Hooks are normal javascript functions that contain common stateful logic which can be reused in multiple components. Name of custom hooks should start with “use” and they can call other hooks.
When we have two javascript functions which implement some common logic. You can create a third function with this common logic and implement it in the other two functions. After all, hooks are just javascript functions.
Let’s look at an example of useArray hook which allows you to carry out any array related operations very easily in all your functional components.
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-arrayutil-js
This hook takes in an array as a parameter and provides the method to modify it. You can include any array operations like add to add an element to the array, removeById to remove an element by id, clear to empty the array.
Now let’s look at how to use this hook in other functional components for example in a shopping list component
https://gist.github.com/KirthiArun/2e356c5fe1cbe5e2c99f44d1ed5ba40e#file-addshoppinglist-js
We get the array method objects in the itemsList variable. Methods like add, removeByIndex come in handy and reduce the number of lines of code we would have otherwise.
We have merely scratched the surface of what you can achieve using react hooks. Since its inception a good number of react hooks have been created by the community. You can find a collection of useful resources for React here – https://github.com/rehooks/awesome-react-hooks