DEV Community

Cover image for Intro to React Hooks
Ryan Moragas
Ryan Moragas

Posted on • Edited on

Intro to React Hooks

If you've used React, you're probably familiar with the struggle of trying to decide if your components should be stateful or functional. Class components, also known as stateful components, can get bulky pretty quickly, but are necessary to hold all of the state that your app needs. Functional components are usually much less code, but rely on stateful components to pass down props for them to utilize. React hooks easily help solve this dilemma, and in this article I'll cover the basics that you need to know to start utilizing them.

First off, let's take a look at what a normal stateful component would look like.

import React from 'react'

class Counter extends React.Component {
 constructor(props) {
   super(props)
   this.state = {
     counter: 0
   }
   this.handleIncrement = this.handleIncrement.bind(this)
 }

 handleIncrement() {
   this.setState({
     counter: this.state.counter += 1
   })
 }

 render() {
   return
     <div>
       <div>{this.state.counter}</div>
       <button onClick={this.handleIncrement}>+</button>
     </div>
 }
}

Above we have a simple stateful component named Counter. We've set the state for a counter starting at 0. We bound the handleIncrement function to the current this at call time, a defined the function increase the counter by 1. Then we render the current state and link the function to a button. This is a pretty simple stateful component, but using hooks can make this even easier.

The first thing that we need to do in order to use Rect hooks is import the hook that we want to use. The hook used for setting state is called 'useState', and we can import it on the first line with react.

Import React, { useState } from ‘react’;

After we import the hook we can then use it in our component. Using the useState hook makes it even easier to set state than how we did it above in our stateful component. We do so by declaring a variable in an array. The first value in the array is the name that we want to use for our state, and the second is the function that we use to set that state. We then set that state to whatever default value we want to give it.

const [counter, setCounter] = useState(0);

The code above can be used to set state just like how we did in our stateful component above, but does so using much less code. Before hooks the only way we could access state like this in functional components was to pass it from a stateful component as props. Hooks allow us to define and change state on the fly from functional components.

import React, { useState } from 'react'

function Counter() {
 const [counter, setCounter] = useState(0)
 function handleIncrement() {
   setCounter(counter + 1)
 }

 return (
   <div>
     <div>{counter}</div>
     <button onClick={handleIncrement}>+</button>
   </div>
 )
}

The snippet above does exactly what the code in our stateful component does, but is noticeably shorter. We no longer have to create all of the code using the constructor or super functions. We also no longer have to use the this keyword when referring to state, or have to bind the function that we use to set the state. We can use hooks not only for setting and manipulating state, but we can also easily manage life cycle methods. To do this we use the useEffect function we simple import it, just like how we imported our useState hook.

Import React, { useState, useEffect } from ‘react’;

Class components manage side effects using life cycle methods, like componentDidMount() or componentDidUpdate(). In functional components we can now use the useEffect() function to perform side effects in functional components. By default, effects run after every completed render. But, you can choose to call it only when certain values have changed by passing an array of variables as a second optional parameter. Passing an empty array as the second parameter will only call useEffect when the app is initially rendered.

  componentDidMount() {
    console.log(`The counter is now ${this.state.counter}`);
  }

  componentDidUpdate() {
    console.log(`The counter is now ${this.state.counter}`);
  }

The snippet above uses componentDidMount to log the counters initial value on the console. We then use componentDidUpdate to log the counters value every time it is changed. With hooks we can manage all of our life cycle methods in one just function.

 useEffect(() => {console.log(`The counter is now ${counter}`);},[counter]);

These are just two of multiple hooks react has for use to utilize. We can even create custom hooks to do whatever we want. They greatly expand the possibilities of what we can do with functional components, and allow us to write in simpler, easier to read code.

Top comments (4)

Collapse
 
barzi92367868 profile image
Barzi

I agree with you on the fact that hooks make life simpler in some conditions. But class components aren't necessarily longer. You don't even need a constructor to declare a state, just use state={counter: 0} and the same can be said for lifecycle components. You could log the value of counter in the render() method without doing it twice in two different methods (didupdate and didmount). I agree with you on the general line, but I think that you tried too hard to put class components in a bad light

Collapse
 
jasonetaylor profile image
Jason

I wouldn't say he tried too hard to put classes in a bad light. His examples are very much the same as anyone else showing what hooks can do. There was a reason the react team released hooks.

Collapse
 
barzi92367868 profile image
Barzi

There are several reasons why they introduced hooks, but brevity isn't one of them, imo

Collapse
 
kimsean profile image
thedevkim

Good post and helpful for ReactJS beginners. Thank you