A sneak peek into React Hooks

Topics

  1. Overview of React Hooks
  2. Why are Hooks created?
  3. Rules to follow
  4. useState and useEffect Hooks
  5. Hooks API Reference

Overview of React Hooks
React.js is an open-source JavaScript-based UI library that uses component-based architecture and is widely used for web and mobile app development. A component in React is an isolated and reusable piece of code.

The components can be of two types – class components and functional components. Prior to v16.8, one could handle state and other React features only using class components. But from v16.8 onwards, React introduced a new pattern called Hooks. With React Hooks, we can use
state, and other React features, can be handled in a functional component as well.

With Hooks, there are absolutely no breaking changes!

  1. Completely opt-in. You can try Hooks in a few components without rewriting any existing code. But you don’t have to learn or use Hooks right now if you don’t want to.
  2. 100% backwards-compatible. Hooks don’t contain any breaking changes.
  3. Available now. Hooks are now available with the release of v16.8.0.

There are no plans to remove classes from React. Hooks don’t replace your knowledge of React concepts.

Why are Hooks created?
There are different reasons for creating Hooks:

  1. No use of Classes: Well, with Hooks, we would no longer have to call super(props), we’d no longer need to worry about binding our methods or this keyword, and we’d no longer have a use for Class Fields and that is the best part.
  2. Reusable stateful logic: If you’ve used React for a while, you may be familiar with patterns like render props and higher-order components that try to solve this. But these patterns require you to restructure your components when you use them, which can be cumbersome and make code harder to follow. Hooks allow you to reuse stateful logic without changing your component hierarchy.
  3. Simplifying complex logic: While creating components for complex scenarios such as data fetching and subscribing to events it is likely that all related code is not organized in one place and is scattered among different life cycle methods. Each lifecycle method often contains a mix of unrelated logic. For example, components might perform some data fetching in componentDidMount and
    componentDidUpdate . However, the same componentDidMount method might also contain some unrelated logic that sets up event listeners, with cleanup performed in componentWillUnmount . Mutually related code that changes together gets split apart, but completely unrelated code ends up combined in a single method. This makes it too easy to introduce bugs and inconsistencies.

Rules to follow

  1. Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions. By following this rule, you ensure that Hooks are called in the same order each time a component renders.
  2. Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions. There is just one other valid place to call Hooks — your own custom Hooks. By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

useState and useEffect Hooks
React provides you with 10 hooks functions, but only 2 of these hooks are going to be used very frequently when you write function components. They are useState and useEffect hooks.

useState hook
We can import the hooks or directly declare them using React.hookName .

// Three ways to import hooks
import React, {useEffect} from “react”;
import useFetch from “./useFetch”;
const [show, setShow] = React.useState(false);

In useState hook there are two parts declared inside square parts. First is the state itself and the second is a function that changes the value of the state. In simple terms handles the changes in the state. From above show is the state and setShow is the function.


useState is one of the most commonly used hooks in React. Now there are multiple approaches to setting the value of the state using the function.

For example:

setColor((oldColor) => {
let newColor = oldColor.filter((color)=> color.id !== id);
return newColor;
}
// the above is the same as
let newColor = oldColor.filter((color)=> color.id !== id);
setColor(newColor)

So, that essentially concludes the basic useState hook, eventually, advanced concepts such as useReducer hook and Redux take over what useState does on simple terms and build upon that.

useEffect hook
The useEffect hook helps create side effects in the app which means that any action that is not on the main component or something that should run in the background and not on the view of the app.

Some examples would be the popups that you see visiting a website, signing up for a subscription, setting up an eventListener and most commonly used to fetch data from the server.

Fun Fact: if you ever encounter a double render of data in your console then it is due to React.StrictMode in the index.js file.

useEffect(() => {
console.log(“call useEffect”);
})

Now, the hook is acting like a function that is re-rendered almost infinitely. So, useEffect can take another parameter along with the initial function and that is an array, called the Dependency array. We can send one or more states or functions to the dependency array. The array is
denoted as ‘[]’ , when left empty the useEffect is run only once at the initial render.

useEffect(()=>{
fetchApi.then(()=>{
setLoading(false)
})
}, [])

It restricts the re-render almost every time but we might encounter an infinite loop from the function that has been passed in the dependency array. So we need a cleanup function. And the keyword “cleanup” is important as React automatically searches for it in a useEffect.

The Flow of useEffect with cleanup function is something like:

(Initial Render + useEffect() call) --> (Re-Render + Cleanup Function + useEffect() call) --> (Re-Render + Cleanup Function + useEffect() call)…

Below is an example for a useEffect where we show a loading gif or pic until the data is fetched. We also are checking if the component is still mounted. This way we prevent memory leaks.

function myComp(){
const [loading, setLoading] = useState(true)
useEffect(()=>{
let mounted = true
apiFetch.then(()=>{
if(mounted){
setLoading(false)
}
})
return function cleanup(){
mounted = false
}
}, [])
return {loading ?
Loading… :
Data Fetched }
}

While fetching data, remember to never call useEffect using async-await. They return a promise, while useEffect is looking for a cleanup function. We can use async-await inside useEffect , but not the hook itself.

One can also build custom Hooks!

Hooks API Reference
For reference, please find the link – Hooks API Reference – React (reactjs.org)

Want to be part of the Andela Community? Then join the Andela Talent Network!

With more than 175,000 technologists in our community, in over 90 countries, we’re committed to creating diverse remote engineering teams with the world’s top talent. And our network members enjoy being part of a talented community, through activities, benefits, collaboration, and virtual and in-person meetups.

All you need to do to join the Andela Talent Network is to follow our simple sign-up process. 

Submit your details via our online application then…

Complete an English fluency test – 15 minutes.

Complete a technical assessment on your chosen skill (Python, Golang, etc.) – 1 hour.

Meet with one of our Senior Developers for a technical interview – 1 hour.


Visit the Andela Talent Network sign-up page to find out more.

If you found this blog useful, check out our other blog posts for more essential insights!

Related Posts