Michael Garrigan

React HOC's

As with many things in software engineering a Higher Order Component or (HOC) seems on the surface to be quite complicated but with careful examination is really a simple design pattern. And even though we are looking at a HOC in the context of React it is important to note that HOCs' are just a design pattern used in building React applications and HOCs' are not defined by or native to React in any way.

I would like to explain two concepts before starting our code that implements bulding a HOC. The first will be 'Higher Order Functions' and second will be 'What is a React Component?'

1. Higher Order Functions or HOF

A HOF is a function that operates on other functions. HOF's are a programming paradigm that stems from functional programming. Not all programming languages make it easy (or allow it at all) to pass a function as a parameter or return a function from a function. But Javascript does and we can use HOFs to create powerful programming techniques and patterns.

Javascript treats functions as 'first class citizens' which means Javascript functions have these attributes:

1) Functions can be stored in a variable and nested in a data structure.

2) Functions can be passed to and returned from functions.

3) Functions can have properties and methods.

Below is a quick look at the three ways a HOF can be used.

Three signatures of HOF's:

1) A function that accepts functions as arguments

        
  function myHOF (function1, value) {
    const result = function1(value) + function1(value);
    return result;
  } 

  // usage
  const double = (value) => {return value + value;} 
  myHOF( double );
        
      

2) A function that returns a function

        
  function myHOF (value) {
    return function () {
      return value+=1;
    }
  } 

  // usage
  myHOF(5)( ); // note the empty paren at the end invokes the returned function
        
      

3) A function that does both

        
  function myHOF (function1, function2, data) {
    return function () {
      return function1(data[0]) + function2(data[1]);
    }
  } 

  // usage
  myHOF(
    value => value * value,
    value => value / value,
    [10, 40]
  )( ); // returns 101
        
      

A higher order function is a very much the same as a higher order component but differs in its inputs and outputs. So a HOF can take a function in as a parameter and returns a new function. Whereas our HOC takes in and returns React Components.

Note: If our HOF is returning a function then our original function will not be be available to us until we call our new function. Once that happens our original function will have access to all variables and parameters defined in the new functions run time via JavaScript's Closure mechanism.

2. What is a React Component?

At a very basic sense a React Component is a function that takes props as a parameter and returns UI. So props as in 'this.props' and UI (user interface) as JSX. And JSX will become what we eventually see on our website as HTML elements.

3. Higher Order Components or HOCs

A HOC is a function that operates on React Components. This programming pattern will give us the ability to 'wrap' any component with additional logic in the form of props and methods.

Attributes of a HOC:
  1. A pure function that has no side effects
  2. Accepts a react component as a parameter and returns a new react component

Note: We have returned a new React component with the original component inside (modified to include extra data). But we will not be able to gain access to the original component until we are using/calling our new component. At that point the new component will return our original component to the front end ui.

What problem does a HOC solve?

HOC's main strength is keeping our code DRY. Where DRY is an acronym for Don't Repeat Yourself. A HOC will define behavior that we would like in our component, so we can use our HOC in multiple locations within our code and use the same HOC to wrap our component.

What problem does a HOC create?

HOC's main weakness that it can override prop names on our components if we are careless. And if we add methods to the original component that are setting state then we can make code that is dificult to understand. And lastly you can chain HOCs and create a very complex statement. Like HOC1(HOC2(HOC3(HOC4(BaseComponent))))


So lets make a HOC !!!


First we will define BaseComponent.

        
  import React, { Fragment } from 'react';
  import hoc from './hoc.js

  const BasicComponent = props => (
    < Fragment >
      <button 
        onClick={ event => 
          props.setRandom(event)
        }
      >
        {
          props.ids.map( id => (
            <p key={id} >
              {`This id number is: ${id}`}
            <p>
          ))
        }
      < / button >
    < / Fragment >
  );

  export default hoc(BaseComponent)
   
        
      

So our BaseComponent has a method passed down that adds a random number into the array called 'ids' when the button is pressed. Next the component is mapping over the array of ids and displaying them in a <p> tag. Pretty simple yes?

Next we define our HOC.

        
  import React, { Component } from 'react';

  const hoc = OriginalComponent => (
    class extends Component { // implicit return 
      state = {
        ids: [ 104, 763 ]
      }

      setRandomValue = event => {
        event.preventDefault();
        const rand = Math.floor(Math.random() * 1000);
        this.setState( prevState => ({
          ids: [ ...prevState.ids, rand ]
        }));
      }

      render() {
        return(
          < OriginalComponent
            ids={this.state.ids}
            setRandom={this.setRandomValue}
            { ...this.props }
          />
        )
      }
    }
  )
    
  export default hoc
        
      

So now the hoc. The first thing to notice is that hoc is just a normal function that accepts a React Component. Next item is the implicit return that is returning a nameless react class component. It is important to remember that we are returning a new React Component that is nameless. So we will not have access to our original React component until the component is acually rendered in our application. The last thing to point our is now if we wanted to add this random number generator that is named 'setRandomValue' and the accompaning ids array we can use this hoc to wrap any component that we would like and share this logic.

Thanks for making it to the end. HAPPY CODING!!!