DEV Community

Jason Mei
Jason Mei

Posted on

An Intro to React Hooks

Introduction

React is an open-source Javascript library that is created and maintained by Facebook. Released in 2013, React is designed for building dynamic user interfaces and front-end applications composed of components, meaning that each piece of the application’s front-end interface is its own individual component. A component is able to receive inputs (called “props”) and return React elements describing how and what should be rendered to the DOM. Understanding the different types of components and how they work is integral to using React hooks.

React Components and Lifecycle

There are two types of components in React - class components and functional components. Class components go through a three-part lifecycle: mounting (the component is initialized and rendered with its props and initial state), updating (the component is changed and re-rendered), and unmounting (the component gets deleted and cleared out of the page). Class components also have access to special “lifecycle” methods that allow you to run code during a particular phase of its lifecycle.

class Clock extends React.Component {
  constructor(props) {
  // initialize component with props and initial state
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
  // run code after component has been rendered to the DOM
  // data fetching requests are usually here
  }

  componentWillUnmount() {
  // run code after component is removed from the DOM
  // cancel data fetching, clear a counter, etc
  }

  render() {
  // outputs component to the DOM (required lifecycle method)
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date}.</h2>
      </div>
    );
  }
}

Traditionally, only class components have access to these lifecycle methods and the ability to manage state, but this changed with the introduction of hooks.

Hooks Explained

Released in February 2019 with React version 16.8, hooks are functions that allow you to "hook into" React state and lifecycle features from a functional component. This largely eliminates the need for classes and leads to more concise and easy-to-read code.

// Class component
import React, { Component } from "react"

class Example extends Component {
   constructor() {
      super();
      this.state = {
         name: "Jason"
      }
   }

   render() {
      return (
        <div>
         <p>Hi, my name is {this.state.name}!</p>
       </div>
      )
   }
}

export default Example
// Functional component with useState hook
import React, { useState } from 'react';

const Example = () => {
  const [name] = useState("Jason");

  return (
    <div>
      <p>Hi, my name is {name}!</p>
    </div>
  );
}

export default Example

Hooks are also "opt-in", meaning that they are completely compatible with existing React apps that use classes. This allows developers to easily experiment and implement hooks into older codebases without fear of breaking anything. React includes many built-in hooks, but the most commonly used hooks are useState and useEffect.

useState

The useState hook declares a "state variable" using array destructuring. The first value is what you're assigning as state, and the second is a function that changes that state. When declaring a state variable, you pass in the initial value of the state into useState().

// you must import hooks at the top of your component
import React, { useState } from 'react';

const Example = () => {
  // declaring a new state variable called "count", and "setCount" is a function that increments the state "count"
  const [count, setCount] = useState(0); // setting the initial state to 0

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

export default Example

useEffect

The useEffect hook replaces the lifecycle methods from class components by allowing us to perform side effects (operations outside of the component like data fetching, event listening, or DOM manipulation) from functional components. useEffect() takes in a callback function and an optional array in which you can specify which variable changes will trigger the effect.

// with no second argument, runs the function on every component render
useEffect(() => {
   functionCall()
},)

// replaces componentDidMount by putting an empty array as second arg, side effect runs once
useEffect(() => {
   functionCall()
}, [])

// by adding variables into the second arg, React will only run the side effect if those variables changed
useEffect(() => {
   functionCall()
}, [watch, these, variables])

//replaces componentWillUnmount when returning a function to clean up side effects within callback
useEffect(() => {
   function doStuff() {
     //effect
   }
   return function cleanup() {
     //remove effect
   }
})

Conclusion

By using React hooks, you no longer need to use classes to manage state and access lifecycle methods within your React components. Everything can be done using functional components. Your code will become cleaner, more concise, and easier to navigate. And best of all, hooks are 100% backwards compatible and do not contain any breaking changes. So go ahead and try implementing hooks in your new or existing React applications. Happy coding!

Oldest comments (0)