Rules of Hooks

Introduction: 

Before proceeding towards the rules of Hooks, we should be very clear about what exactly is Hooks.

Hooks are special features added to react 16.8. Using Hooks, we can use state and other react features without even writing a class. Hooks are the javascript function, which when implemented, two rules should be followed. A linter plugin is provided to implement these rules automatically. Sounds confusing, right? Let’s move towards a deep understanding of the rules with examples.

 

Working of the rules of Hooks:

First rule:

 

  • Hooks should be called only at the top level

Hooks should never be called inside loops, conditions, or nested functions. Rather, it should always be called at the top-notch, before any returns. This rule also ensures that Hooks are called each time in the same order every time a function component renders. It helps to preserve the state of Hooks between useState and useEffect function calls. 

 

Second rule:

 

  • Hooks should be called from React functions

Avoid calling Hooks from javascript functions directly. Instead, call them react function components and from custom Hooks. This rule also ensures that all stateful logic in a component is clearly visible from its source code. 

 

ESLint Plugin:

There exists an ESLint Plugin called eslint-plugin-react-hooks. The above two rules are implemented with this plugin. The structure looks like this:

 

npm install eslint-plugin-react-hooks --save-dev

 

// Your ESLint configuration.

{

  "plugins": [

    // ...

    "react-hooks"

  ],

  "rules": {

    // ...

    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks.

    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies.

  }

}

 

Working:

Now, as we have learned about the rules, let’s figure out the reason behind the existence of these rules:

 

We have already learned that multiple State or Effect Hooks in a single component. The structure looks like this:

 

function Form() {

  // 1. Use the name state variable.

  const [name, setName] = useState('Mary');

 

  // 2. Use an effect for persisting the form.

  useEffect(function persistForm() {

    localStorage.setItem('formData', name);

  });

 

  // 3. Use the surname state variable.

  const [surname, setSurname] = useState('Poppins');

 

  // 4. Use an effect for updating the title.

  useEffect(function updateTitle() {

    document.title = name + ' ' + surname;

  });

  // ...

}

 

But the question which you might be thinking is how does react know which state corresponds to which useState call? Come let’s figure it out.

 

The answer lies in the fact that React relies on the order in which Hooks are called. In our example, the order of the Hook calls is the same for every render.

 

// ------------

// First render.

// ------------

useState('Coding')           // 1. Initialize the name state variable with 'Coding'.

useEffect(persistForm)       // 2. Add an effect for persisting the form.

useState('Ninjas')           // 3. Initialize the surname state variable with 'Ninjas'.

useEffect(updateTitle)       // 4. Add an effect for updating the title.

 

// -------------

// Second render.

// -------------

useState('Coding')           // 1. Read the name state variable (argument is ignored).

useEffect(persistForm)       // 2. Replace the effect for persisting the form.

useState('Ninjas')          // 3. Read the surname state variable (argument is ignored).

useEffect(updateTitle)       // 4. Replace the effect for updating the title.

 

// ...

 

Until the order of Hook calls is the same between renders, some local state is associated with each of them. But what if we put a Hook call inside a condition?

 

// The first rule breaks,due to using a Hook in a condition.

  if (name !== '') {

    useEffect(function persistForm() {

      localStorage.setItem('formData', name);

    });

  }

 

Here, the name !== ‘ ’. This call is true for the first render call. But, before the next call, the user might clear the form, making the condition false. Now, as we have skipped the order of Hook during rendering, the order of Hook call become different:

 

useState('Coding')           // Read the name state variable (argument is ignored).

// useEffect(persistForm)    // This Hook was skipped!.

useState('Ninjas')          // 2 (but was 3). Fail to read the surname state variable.

useEffect(updateTitle)      // 3 (but was 4). Fail to replace the effect.

 

Here, react fails to recognize the result of the second useState Hook call. Just like the previous render call, react expects that the second Hook call in the component also points to persistForm effect, just like the previous calls. Since we skipped one call, afterward, every call will continue skipping one-one calls leading to bugs. 

 

This justifies the reason why Hooks must be called on the top level of our components

 

Frequently asked questions:

  1. What are hooks in React JS?

 

Hooks are the special kind of functions that allow hook-up or use of the react state and function lifecycle features. Hooks cannot work inside classes.

 

  1. State the difference between react Hooks and redux?

 

Redux contains the global state and the actions to be performed. While react hooks handle the local component state. 

 

  1. What does useState hook do?

 

useState hook is a unique function that takes the initial state as an argument and returns the updated entries.

 

  1. Is it possible to use a hook inside a hook?

 

No, it’s not possible to use a hook inside a hook. Doing so will violate the rule of Hooks which states that no two hooks can be initialized one within another.

 

Key Takeaways:

In this article, we have learned about the rules in Hooks. And finally, take a look at why they came into existence. 

Keeping the theoretical knowledge at our fingertips helps us get about half the work done. To gain complete understanding, practice is a must. To gain complete understanding, visit our page.
 

Happy Learning

 

~ Pradipta Choudhury

 

Was this article helpful ?
0 upvotes

Comments

No comments yet

Be the first to share what you think