Jon Rumsey

An online markdown blog and knowledge repository.


Project maintained by nojronatron Hosted on GitHub Pages — Theme by mattgraham

React Hooks

Review React Hooks to learn what they are, and how and when to use them.

Provide links to additional references as well as code snippets where possible.

Table of Contents

Overview

Hooks are new in v.16.8 and provide Functional Components similar capabilities to what React Class Components are borne with.

Hooks features include:

Other Hooks benefits:

Components should just be Functions, and Hooks are simply function calls. Therefore, "custom Hooks" can be created for your specific needs.

Important!: Do NOT call a Hook inside of a conditional. They must be called at the top of the Component.

Hooks as proposed by ReactJS: [React Conf 2018 Presentation]

Migrating From Class to Function Components

This is necessary in order to use React Hooks (or create your own). Follow these general steps to get going rapidly:

  1. Change the Component signature from export default class MyFunction extends React.Component... to export default function MyFunction()
  2. If the class received props from a parent Component update the signature to be export default function MyFunction({prop, ...}) to include the actual parameters passed-in by the parent.
  3. Any this.props statements need to be renamed. Functional Components do not support this so these props need to be renamed and set in step 2.
  4. Remove the render(){} code blocks. All render code is now just code-block within the Function.
  5. If enforcing PropTypes, include the definition just after the last Functional Component closing brace: MyFunction.propTypes = { propa: PropType.object, ... };
  6. If the Component was updating state, then import useState and refactor the setState() function calls to use the appropriate setN array item instead.
  7. Remove the { Component } import statement, it is no longer needed.

UseState

Import: import React, { useState } from 'react';

Leverage the Hook:

export default function MyFunction(props) {
  const [name, setName] = useState('MyName');
  // declares a State with properties 'name' and 'setName'
  // initializes 'name' with a value 'MyName' to start
}

Reference an event handler:

export default function MyFunction(props) {
  const [name, setName] = useState('MyName');
  
  function handleNameChange(event) {
    setName(event.target.value);
  }
  // no longer necessary to bind the event handler
  // to a class in order to get access to it
}

Context

Reading Context.

Like global variables for a subtree.

Allows reading current user language or visual theme.

Import: import { ThemeContext } from './context';

Enables using: <ThemeContext.Consumer> component.

Example implementing a theme from a CSS file:

import { ThemeContext } from './context';

// inside of a class component...

  return (
    <ThemeContext.Consumer>
      {theme => (
        // theme is just a css class
        <section classname={theme}>
          // more jsx here
        </section>
      )}
    </ThemeContext.Consumer>
  );
}

Similarly, <LocaleContext.Consumer> enables setting end-user language.

UseContext Hook simplifies this somewhat.

import React, { useContext } from 'react';
import { ThemeContext } from './context';

export default function MyFunction(props) {
  const theme = useContext(ThemeContext);
  // this reads context AND SUBSCRIBES to changes!

  // more code
  return {
    <section className={theme}>
      // more jsx here
    </section>
  }
}

UseEffect and Side Effects

Import: import React, { useEffect } from 'react';

Declare the effect inside the component definition to allow access to State/useState.

UseEffect to display a variable to the active browser tab aka 'document title':

import React, { useEffect } from 'react';

export default function MyFuction(props) {
  const [name, setName] = useState('Alpha');
  
  useEffect(()=>{
    document.title = myNewTitle;
  });

  function handleNameChange(e) {
    setName(e.target.value);
  }
}

Multple useEffects statements can be made for unrelated data properties.

Any effect can optionally return a function. Call the function using an arrow function to encapsulate functions like window.removeEventListener(name, callback).

This of useEffect as 'componentDidMount', 'componentDidUpdate' among other lifecycle events.

Custom Hooks

  1. Develop a function as you normally would: function useFuncname(){ ... return result }
  2. Add a new const variable to store the output in the calling function: const customResult = useFuncname();

Convention:

Custom Hooks are javascript functions:

Create your own abstractions without adding to "wrapper hell".

Moving to Hooks

There are more in the faq: From Classes to Hooks

useRef

Enables:

Do/Nots:

Support

React 16.8+

React Native 0.59+

Unittesting: Treat like a Functional Component. Check out these testing recipes

Linting:

Developing with Hooks Going Forward

Recommend developing Functional Components with Hooks, instead of Class Components going foward.

Functional w/ Hooks is fully compatible with Classes in the same React Tree.

References

Reactjs.org Hooks at a Glance

Reactjs.org Hooks API Reference

React Conf 2017 video on YouTube

Return to continuing education index