DEV Community

Kevin Downs
Kevin Downs

Posted on

React Hooks

This week I would like to take a look into a relatively new feature introduced to React: Hooks. If you are anything like myself, you may have been working with React for a bit and heard people talking about Hooks but never really looked into what they actually were. Maybe you filed them under that little folder in your brain labeled "I should probably check that out at some point" and went along working on the projects you were already involved with. Well the day came where I finally decided to double click that little folder and take a look, and I thought why not walk through it for others that are just clicking that little folder too.

What's a Hook?

Hooks are an addition made in React 16.8. In the simplest terms, they are functions that allow you to use state and life-cycle features inside functional components. They do not work inside of classes and are intended to allow you to use React without classes. React provides a few built-in hooks like useState and useEffect, but also allow you to create custom hooks. This makes it easy to share hooks between components and even to reuse stateful logic without the need to change your component hierarchy.

There are two simple rules that you need to know about and follow when using hooks:

  1. Only call Hooks at the top level.
  2. Only call Hooks from React functions.

The two rules echo the same principle that Hooks are strictly for use within functional React components at the top level. This means that you cannot use hooks inside loops or conditions somewhere in your class and that you cannot use them within class components. (Though this may sound a bit self explanatory as the entire idea behind hooks is to not use class components) They cannot be called within regular JavaScript functions, but can be called from custom hooks and of course inside functional components.

Now that we have an idea of what Hooks are and what their purpose is, I'd like to show how one of the most used built in hooks can be used: useState.

useState

For this example, I'm going to include some example code from the React docs that explain the usage of useState. You will see the same class in a traditional class component, and then the same class as a functional component using Hooks to gain access to the state functionality.

// Example class component

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button>
      </div>
    );
  }
}

// Example functional component using Hooks

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

You can see that the two look pretty similar. The difference here is that we can avoid having to create a class component and dealing with the constructor to gain access to state by importing the useState Hook in a functional component. Let's take a look at how it works.

First, we import the useState hook:

import React, { useState } from 'react';

Now normally in a class component we would go into the constructor function and assign this.state to an object value of the data we want to have in our state. With Hooks though, we are able to call useState to get the same effect. You may be a bit confused by the odd square bracket syntax so let's break down what exactly is going on here.

The code: const [count, setCount] = useState(0);

useState declares a "state variable" that will be preserved between function calls in the same way state is preserved in a class component. It takes in an initial value as an argument and returns a pair of values: the current state and a function that updates it. We use array destructuring here to be able to use those returned values directly in our component. You can name these variables whatever you would like, but using the pattern "thing", "setThing" helps to keep things clean and organized.

You are able to repeat this for as many state variables as you might need. Here is an example:

function ExampleWithManyStates() {
  // Declare multiple state variables!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

You can also see in the full component example above we can use these variables directly in our component code. We can just use count to get its current values and use setCount by passing in the value that count should be updated to.

Conclusion

React Hooks are a great way to reduce the use of class components in your code and allow for a lot of flexibility in terms of extracting and reusing bits of code that you otherwise would not be able to. There are a host of other Hooks as well that provide even more functionality such as useEffect which allows you to avoid using a lot of different life-cycle methods. If you found this write up interesting, go ahead and take a look over at the React docs. They provide a great wealth of information on different ways you can start using Hooks in your React projects!

If you liked this post, feel free to follow me elsewhere on Twitter, Github, or LinkedIn. Happy Coding!

Latest comments (0)