Article

What are Hooks in Programming?

Discover how hooks can enhance your code's flexibility by allowing custom modifications to software behavior. Read more to optimize your programming skills.

Hooks let you insert custom logic into specific points of a system’s lifecycle. React Hooks (useState, useEffect) allow function components to manage state and lifecycle events. Class components in React used “lifecycle methods” (like componentDidMount) that act similarly to hooks.

Mongoose Hooks (also called middleware) let you run functions before or after database operations (e.g. pre('save'), post('remove')). Git Hooks are scripts triggered at key Git events (e.g. pre-commit, post-merge) to automate workflow tasks. Common theme : All these hooks “intercept” or extend default behavior at certain stages.

Middleware vs Hooks : Middleware is broader; hooks are more focused on lifecycle events within a system. Summary definition : A hook is a targeted type of middleware used to modify behavior during specific lifecycle events.

Nonetheless, the concept of a hook in programming pops up in a variety of libraries and software across the stack. React on the front end, Mongoose on the back end, and even Git on the DevOps side. These are all very different tools, so it might be difficult to see how they could possibly relate, but their “hooks” all have something in common. Let’s look at a couple of examples and see if we can get a handle on what a “hook” really is.

Let’s start by looking at what are arguably the most prominent hooks for web developers at the moment; React hooks (if you don’t know React, here’s a great place to get started ).

Basically, in React, hooks are functions that you can put in your components that can do a lot of powerful things, such as managing component state and controlling a component’s lifecycle (mounting, updating, and unmounting). The most commonly used hooks are useState and useEffect.

The useState hook manages the storage, persistence, and updating of data that is relevant to a component (put simply, its state). const [friends, setFriends] = useState([]);

This one line of code is powerful. It creates a piece of state (let’s say we’re making a social media site. Here, we’re initializing a variable called friends as an empty array) and a function you can use to update the count variable that we call setFriends. Using it allows React to performantly rerender your component with updates to its state.

useEffect lets you control how your component behaves throughout its lifecycle (mounting, updating, and unmounting).

This call to useEffect will fetch a list of friends and update the friends array we declared earlier when a component mounts for the first time. The call to setFriends will trigger a rerender.

But in JavaScript, classes can get confusing, and class based components can get messy. The hooks included in React 16.8 allow you to manage state and lifecycle within a component written as a function, instead of a class. Or, as the docs say, they let your functional components “hook into” state and lifecycle features.

Does this mean that class components also “hook into” state and lifecycle?

It would appear so. Even before the hooks in version 16.8 were announced, people were referring to the functions that control the lifecycle of a class component as “lifecycle hooks” .

Even though the React docs don’t refer to them this way, a lot of other people across the internet called the lifecycle methods for class components “hooks” too. .then(friends => this.setState({friends}));

This code, implementing the componentDidMount lifecycle method, does exactly what the above call to useEffect does (assuming we initialized state in a constructor), just in a class component, the only way you could do this kind of thing pre-hooks.

And to be fair, the lifecycle methods for classes and the hooks for functional components both fit PC Matic’s definition of a “hook” equally well. The React devs may have chosen this name for the new update just to be catchy (no pun intended, but I’m rolling with it anyway), but it might be accurate to describe these older lifecycle methods as “hooks” too.

Both React hooks for functional components and “lifecycle hooks” for classes “augment the behavior of an application” by “intercepting function calls”. In short, you’re injecting your own code into the flow of React. So what exactly is the difference between middleware and hooks?

Well, that’s where this gets a little annoying. Let’s look at Mongoose, a JavaScript library that lets you easily work with MongoDB, a popular NoSQL database. Mongoose also has some features called hooks. But let’s see what the Mongoose docs say about them. “Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions.”

I wish I could tell you the difference between these terms. But when docs for a popular JavaScript library treat the two terms like synonyms, we get a little stuck.

Let’s take a closer look at what Mongoose hooks (or middleware) do, and maybe that’ll help clear things up. There seem to be two main kinds of Mongoose hook methods: “post” and “pre” hooks. console.log(‘right about to save to the database’);

Using a pre hook and passing in the string ‘save’, the provided callback function will run before anything is saved into your database. console.log(‘%s has been removed’, doc._id);

Using a post hook and passing in the string remove will run the provided callback after an entry has been removed from your database.

There are many ways to combine pre and post hooks with parts of the MongoDB lifecycle, but here’s what they all have in common - these hooks (or middleware) allow you to inject your own logic into various parts of that lifecycle. Before something is saved, after something is saved, before an entry is found, or after an entry is updated, etc, you can use these functions to run your own custom code.

The similarities are clear. Without the confusion with “middleware,” I’d say the concept of a “hook” is starting to make a lot of sense.

You can spend a long time online searching for a meaningful definition of the term “hook” (and, for that matter “middleware”). But let’s think about what these three examples of hooks have in common so we can come up with a definition that makes sense.

How are Git hooks similar to React hooks and Mongoose hooks? They all let you augment the default performance of a system by injecting your own logic into certain places in that system’s lifecycle.

Perhaps a hook is a specific type of middleware meant to target a certain point in the lifecycle of a system? These terms are all somewhat nebulous, but I think this could be a valuable and sensible way of looking at them.