The slightly misleading terminology of react hooks

jackmellis

Jack

Posted on February 5, 2021

The slightly misleading terminology of react hooks

So react hooks are awesome, they make components much simpler, they let you abstract your component logic and completely do away with class components.

However; the names of these hooks are somewhat misleading. Especially after react went all functional on us with function components.

Allow me to elaborate:

Side Effects

What is a side effect? A side effect is when a function changes another part of an application outside of its own scope:

function goHome() {
  window.location.href = '/home';
}
Enter fullscreen mode Exit fullscreen mode

Calling this function is updating the window location, which is a global variable and isn't part of its own scope, so it's a side effect.

It's also worth quickly also covering side effect's partner-in-crime:

Idempotent

An idempotent function will return the same value for the same set of inputs every time.

function getPath() {
  return window.location.pathname;
}
Enter fullscreen mode Exit fullscreen mode

This function is not idempotent. If the location were to change, you would get a different result.

With that out of the way, let's talk about useEffect:

useEffect

Accepts a function that contains imperative, possibly effectful code.

useEffect(() => {
  window.location.href = '/home';
}, []);
Enter fullscreen mode Exit fullscreen mode

The useEffect hook allows you to do effectful behaviour inside a functional component.

If you do a side effect inside useEffect, react pushes that side effect to the end of the render cycle. In react terms, useEffect is about protecting the render cycle, not about removing side effects.

Why is this distinction important? We often talk about react components as being "pure". A pure component should be side-effect-free and idempotent. Wrapping your side effects in useEffect does not mean your component is still pure.

useState

I've seen many people say things like "we don't need smart/dumb components now we have hooks"

I don't want to go in-depth into patterns and architecture, but just because you're using useState instead of redux, etc, you're still introducing state into a component. This breaks a component's idempotency.

For every piece of state a component manages, the harder it is to reason about, test, and control that component.

Tl;dr useState is no different to any other component state - it is not functional.

Function vs Functional component

Okay something that I only really noticed recently: we always talk about functional components but actually, the docs refer to these as function components. What's the difference?

I believe the difference is this:

A functional component adheres to the rules of Functional Programming. It is idempotent, pure, and stateless.

A function component is just any old component that just happens to be a function.

That's a pretty big discrepancy. When we're talking about function components, do we care about whether it's a functional component?

I used to believe that yes; any function component should be side-effect and state free. Now I'm not so sure.

Conclusion

We've definitely got some confusing terminology here. useEffect is not offering some way of keeping effects "out" of your component. And a function component is not the same as a functional component.

Should I stop using hooks?

Absolutely not. Hooks are awesome. I just want us to be mindful that hooks are not some magical construct that preserves function purity. If your component has state or causes side effects, useState and useEffect do not change this fact.

💖 💪 🙅 🚩
jackmellis
Jack

Posted on February 5, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related