Wednesday, July 27, 2016

Higher Order Components: A React Application Design Pattern

In this article we will discuss how to use Higher Order Components to keep your React applications tidy, well structured and easy to maintain. We’ll discuss how pure functions keep code clean and how these same principles can be applied to React components.

Pure Functions

A function is considered pure if it adheres to the following properties:

  • All the data it deals with are declared as arguments
  • It does not mutate data it was given or any other data (these are often referred to as side effects).
  • Given the same input, it will always return the same output.

For example, the add function below is pure:

function add(x, y) {
  return x + y;
}

However, the function badAdd below is impure:

var y = 2;
function badAdd(x) {  
  return x + y;
}

This function is not pure because it references data that it hasn’t directly been given. As a result, it’s possible to call this function with the same input and get different output:

var y = 2;
badAdd(3) // 5
y = 3;
badAdd(3) // 6

To read more about pure functions you can read “An introduction to reasonably pure programming” by Mark Brown.

Whilst pure functions are very useful, and make debugging and testing an application much easier, occasionally you will need to create impure functions that have side effects, or modify the behavior of an existing function that you are unable to access directly (a function from a library, for example). To enable this we need to look at higher order functions.

Higher Order Functions

A higher order function is a function that when called, returns another function. Often they also take a function as an argument, but this is not required for a function to be considered higher order.

Let’s say we have our add function from above, and we want to write some code so that when we call it we log the result to the console before returning the result. We’re unable to edit the add function, so instead we can create a new function:

function addAndLog(x, y) {  
  var result = add(x, y);
  console.log('Result', result);
  return result;
}

We decide that logging results of functions is useful, and now we want to do the same with a subtract function. Rather than duplicate the above, we could write a higher order function that can take a function and return a new function that calls the given function and logs the result before then returning it:

function logAndReturn(func) {  
  return function() {  
    var args = Array.prototype.slice.call(arguments);
    var result = func.apply(null, args);
    console.log('Result', result);
    return result;
  }
}

Now we can take this function and use it to add logging to add and subtract:

var addAndLog = logAndReturn(add);
addAndLog(4, 4) // 8 is returned, ‘Result 8’ is logged

var subtractAndLog = logAndReturn(subtract);
subtractAndLog(4, 3) // 1 is returned, ‘Result 1’ is logged;

logAndReturn is a HOF because it takes a function as its argument and returns a new function that we can call. These are really useful for wrapping existing functions that you can’t change in behavior. For more information on this, check M. David Green’s article “Higher-Order Functions in JavaScript which goes into much more detail on the subject.

Additionally you can check out this CodePen, which shows the above code in action.

Higher Order Components

Moving into React land, we can use the same logic as above to take existing React components and give them some extra behaviours.

In this section we're going to use React Router, the de facto routing solution for React. If you'd like to get started with the library I highly recommend the React Router Tutorial on GitHub.

React Router’s Link component

React Router provides a <Link> component that is used to link between pages in a React application. One of the properties that this <Link> component takes is activeClassName. When a <Link> has this property and it is currently active (the user is on a URL that the link points to), the component will be given this class, enabling the developer to style it.

This is a really useful feature, and in our hypothetical application we decide that we always want to use this property. However, after doing so we quickly discover that this is making all our <Link> components very verbose:

<Link to="/" activeClassName="active-link">Home</Link>
<Link to="/about" activeClassName="active-link">About</Link>
<Link to="/contact" activeClassName="active-link">Contact</Link>

Notice that we are having to repeat the class name property every time. Not only does this make our components verbose, it also means that if we decide to change the class name we’ve got to do it in a lot of places.

Continue reading %Higher Order Components: A React Application Design Pattern%


by Jack Franklin via SitePoint

No comments:

Post a Comment