Here Are 7 Ways Higher Order Functions Can Improve Your Life
Tags: react, javascript, node, webdev
Published: 2019-06-21 20:42:42

Find me on [medium](https://medium.com/@jsmanifest).

One of the fundamental building blocks of JavaScript are functions. That's enough to intrigue anyone about the semantics of functions when learning JavaScript.

But functions are _much_ more intriguing than that.

"Like what", you ask?

They can become _higher order functions_--functions that take other functions as arguments, or functions that return functions as their output.

There's a whole lot of _functions_ going on in that line--and JavaScript is _no different_. In JavaScript, functions are _everywhere_. And _you_ should feel blessed that they are!

Here are 7 Ways Reasons Higher Order Functions Can Improve Your Life:

## 1. They Enhance Your Existing Code, Increasing Confidence

![higher order functions can enhance your existing code](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/7-ways-higher-order-functions-can-improve-your-life/1.jpg)

Imagine a function who's task is to retrieve a list of frogs from an API, uses the returned list to calculate the average width of tongues of the frogs and returns the result.

An example would be something like:

```js
import axios from 'axios'

const getFrogs = async (params) => {
  try {
    const response = await axios.get(
      'https://frogs-and-their-tongues.com',
      params,
    )
    const frogs = response.data.result
    return frogs
  } catch (error) {
    throw error
  }
}

const calcAverageWidthOfTongues = async (params) => {
  try {
    const frogs = await getFrogs(params)
    const tongueWidths = frogs.reduce((sum, frog) => {
      return sum + frog.tongueWidth
    }, 0)
    const averageWidth = tongueWidths / frogs.length
    return averageWidth
  } catch (error) {
    throw error
  }
}

calcAverageWidthOfTongues({
  username: 'bob',
  password: 'the_builder100',
})
  .then((result) => {
    console.log(result)
  })
  .catch((error) => {
    console.error(error)
  })
```

As it is now, we are restricted to only returning a number. But what if there was a way to transform it into an object _without changing the original function_?

The _enhancement_ here is having the ability to pass in additional options to customize and transform the output for better control:

```jsx
import axios from 'axios'

const getFrogs = async (params) => {
  try {
    const frogs = await axios.get('https://frogs-and-their-tongues.com', params)
    return data
  } catch (error) {
    throw error
  }
}

const calcAverageWidthOfTongues = async (params) => {
  try {
    const frogs = await getFrogs(params)
    const tongueWidths = frogs.reduce((sum, frog) => {
      return sum + frog.tongueWidth
    }, 0)
    const averageWidth = tongueWidths / frogs.length
    return averageWidth
  } catch (error) {
    throw error
  }
}

const useTongueObj = (fn, options) => {
  return async (params) => {
    const newParams = { ...params }
    if (options.limit !== undefined) {
      newParams.limit = options.limit
    }

    let averageWidth = await fn(newParams)

    if (typeof options.multiplyBy === 'number') {
      averageWidth = averageWidth * options.multiplyBy
    }

    return {
      averageWidth,
      multiplied: typeof options.multiplyBy === 'number',
      size: averageWidth < 2 ? 'small' : 'large', // size in inches
    }
  }
}

const calcTongueWidths = useTongueObj(calcAverageWidthOfTongues, {
  multiplyBy: 2,
})

calcTongueWidths({ limit: 10 })
  .then((tongueObj) => {
    console.log(tongueObj)
    /*
      result:
        {
          averageWidth: 8,
          multiplied: true,
          size: 'large'
        }
    */
  })
  .catch((error) => {
    console.log(result)
  })
```

## 2. They Save Precious, Valuable Time

![higher order functions can help save precious and valuable time](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/7-ways-higher-order-functions-can-improve-your-life/2.jpg)

Let me give a real life example as I'd like to put a little more emphasize on this one.

One of the greatest benefits of higher order functions is that when used correctly, it will save _a lot_ of time for _you_ and for _those around you_.

At my job, we used [react-toastify](https://github.com/fkhadra/react-toastify) to display notifications. We used it _every where_. In addition, they also make great escape hatches for quick last minute UX decisions: "How should we handle this error? Just display a toast notification!" Done.

However, we started noticing that when the app became larger and the level of complexity was creeping up on us, our toast notifications were becoming too frequent. This is fine--however, we didn't have a way of preventing duplicates. This meant that some toast notifications were showing up multiple times on the screen even when they were _exactly the same_ as the toast above it.

So we ended up leveraging the api that the library provides to help remove active toast notifications by _id_ using _toast.dismiss()_.

In order to explain the parts ahead, it's probably a good idea to show the file we were importing toasts from before proceeding:

```jsx
import React from 'react'
import { GoCheck, GoAlert } from 'react-icons/go'
import { FaInfoCircle } from 'react-icons/fa'
import { MdPriorityHigh } from 'react-icons/md'
import { toast } from 'react-toastify'

/*
  Calling these toasts most likely happens in the UI 100% of the time.
  So it is safe to render components/elements as toasts.
*/

// Keeping all the toast ids used throughout the app here so we can easily manage/update over time
// This used to show only one toast at a time so the user doesn't get spammed with toast popups
export const toastIds = {
  // APP
  internetOnline: 'internet-online',
  internetOffline: 'internet-offline',
  retryInternet: 'internet-retry',
}

// Note: this toast && is a conditional escape hatch for unit testing to avoid an error.
const getDefaultOptions = (options) => ({
  position: toast && toast.POSITION.BOTTOM_RIGHT,
  ...options,
})

const Toast = ({ children, success, error, info, warning }) => {
  let componentChildren
  // Sometimes we are having an "object is not valid as a react child" error and children magically becomes an API error response, so we must use this fallback string
  if (!React.isValidElement(children) && typeof children !== 'string') {
    componentChildren = 'An error occurred'
  } else {
    componentChildren = children
  }
  let Icon = GoAlert

  if (success) Icon = GoCheck
  if (error) Icon = GoAlert
  if (info) Icon = FaInfoCircle
  if (warning) Icon = MdPriorityHigh

  return (
    <div style={{ paddingLeft: 10, display: 'flex', alignItems: 'center' }}>
      <div style={{ width: 30, height: 30 }}>
        <Icon style={{ color: '#fff', width: 30, height: 30 }} />
      </div>
      <div style={{ padding: 8, display: 'flex', alignItems: 'center' }}>
        &nbsp;&nbsp;
        <span style={{ color: '#fff' }}>{componentChildren}</span>
      </div>
    </div>
  )
}

export const success = (msg, opts) => {
  return toast.success(<Toast success>{msg}</Toast>, {
    className: 'toast-success',
    ...getDefaultOptions(),
    ...opts,
  })
}

export const error = (msg, opts) => {
  return toast.error(<Toast error>{msg}</Toast>, {
    className: 'toast-error',
    ...getDefaultOptions(),
    ...opts,
  })
}

export const info = (msg, opts) => {
  return toast.info(<Toast info>{msg}</Toast>, {
    className: 'toast-info',
    ...getDefaultOptions(),
    ...opts,
  })
}

export const warn = (msg, opts) => {
  return toast.warn(<Toast warning>{msg}</Toast>, {
    className: 'toast-warn',
    ...getDefaultOptions(),
    ...opts,
  })
}

export const neutral = (msg, opts) => {
  return toast(<Toast warning>{msg}</Toast>, {
    className: 'toast-default',
    ...getDefaultOptions(),
    ...opts,
  })
}
```

Now bear with me, I know this might not look appealing. But I promise it will get better in two minutes.

This is what we had in a separate component to check if a previous toast was already on the screen. And if there was, it will attempt to remove that toast and re-display the new toast.

```jsx
import { toast } from 'react-toastify'

import {
  info as toastInfo,
  success as toastSuccess,
  toastIds,
} from 'util/toast'

const onOnline = () => {
  if (toast.isActive(toastIds.internetOffline)) {
    toast.dismiss(toastIds.internetOffline)
  }
  if (toast.isActive(toastIds.retryInternet)) {
    toast.dismiss(toastIds.retryInternet)
  }
  if (!toast.isActive(toastIds.internetOnline)) {
    toastSuccess('You are now reconnected to the internet.', {
      position: 'bottom-center',
      toastId: toastIds.internetOnline,
    })
  }
}

const onOffline = () => {
  if (!toast.isActive(toastIds.internetOffline)) {
    toastInfo('You are disconnected from the internet right now.', {
      position: 'bottom-center',
      autoClose: false,
      toastId: toastIds.internetOffline,
    })
  }
}

useInternet({ onOnline, onOffline })

return <App />
```

This was working fine--however, we had other toasts throughout the app that needed to be modified the same way. We had to go through every file that displays a toast nofication to remove duplicates.

When we think of _going through every file_ in 2019, we immediately knew that it wasn't the solution. So we looked at the `util/toast.js` file and refactored that to solve our problem instead. Here's what it looked like afterwards:

> src/util/toast.js

```jsx
import React, { isValidElement } from 'react'
import isString from 'lodash/isString'
import isFunction from 'lodash/isFunction'
import { GoCheck, GoAlert } from 'react-icons/go'
import { FaInfoCircle } from 'react-icons/fa'
import { MdPriorityHigh } from 'react-icons/md'
import { toast } from 'react-toastify'

/*
  Calling these toasts most likely happens in the UI 100% of the time.
  So it is safe to render components/elements as toasts.
*/

// Keeping all the toast ids used throughout the app here so we can easily manage/update over time
// This used to show only one toast at a time so the user doesn't get spammed with toast popups
export const toastIds = {
  // APP
  internetOnline: 'internet-online',
  internetOffline: 'internet-offline',
  retryInternet: 'internet-retry',
}

// Note: this toast && is a conditional escape hatch for unit testing to avoid an error.
const getDefaultOptions = (options) => ({
  position: toast && toast.POSITION.BOTTOM_RIGHT,
  ...options,
})

const Toast = ({ children, success, error, info, warning }) => {
  let componentChildren
  // Sometimes we are having an "object is not valid as a react child" error and children magically becomes an API error response, so we must use this fallback string
  if (!isValidElement(children) && !isString(children)) {
    componentChildren = 'An error occurred'
  } else {
    componentChildren = children
  }
  let Icon = GoAlert
  if (success) Icon = GoCheck
  if (error) Icon = GoAlert
  if (info) Icon = FaInfoCircle
  if (warning) Icon = MdPriorityHigh
  return (
    <div style={{ paddingLeft: 10, display: 'flex', alignItems: 'center' }}>
      <div style={{ width: 30, height: 30 }}>
        <Icon style={{ color: '#fff', width: 30, height: 30 }} />
      </div>
      <div style={{ padding: 8, display: 'flex', alignItems: 'center' }}>
        &nbsp;&nbsp;
        <span style={{ color: '#fff' }}>{componentChildren}</span>
      </div>
    </div>
  )
}

const toaster = (function() {
  // Attempt to remove a duplicate toast if it is on the screen
  const ensurePreviousToastIsRemoved = (toastId) => {
    if (toastId) {
      if (toast.isActive(toastId)) {
        toast.dismiss(toastId)
      }
    }
  }

  // Try to get the toast id if provided from options
  const attemptGetToastId = (msg, opts) => {
    let toastId
    if (opts && isString(opts.toastId)) {
      toastId = opts.toastId
    } else if (isString(msg)) {
      // We'll just make the string the id by default if its a string
      toastId = msg
    }
    return toastId
  }

  const handleToast = (type) => (msg, opts) => {
    const toastFn = toast[type]
    if (isFunction(toastFn)) {
      const toastProps = {}
      let className = ''
      const additionalOptions = {}
      const toastId = attemptGetToastId(msg, opts)
      if (toastId) additionalOptions.toastId = toastId
      // Makes sure that the previous toast is removed by using the id, if its still on the screen
      ensurePreviousToastIsRemoved(toastId)
      // Apply the type of toast and its props
      switch (type) {
        case 'success':
          toastProps.success = true
          className = 'toast-success'
          break
        case 'error':
          toastProps.error = true
          className = 'toast-error'
          break
        case 'info':
          toastProps.info = true
          className = 'toast-info'
          break
        case 'warn':
          toastProps.warning = true
          className - 'toast-warn'
          break
        case 'neutral':
          toastProps.warning = true
          className - 'toast-default'
          break
        default:
          className = 'toast-default'
          break
      }
      toastFn(<Toast {...toastProps}>{msg}</Toast>, {
        className,
        ...getDefaultOptions(),
        ...opts,
        ...additionalOptions,
      })
    }
  }

  return {
    success: handleToast('success'),
    error: handleToast('error'),
    info: handleToast('info'),
    warn: handleToast('warn'),
    neutral: handleToast('neutral'),
  }
})()

export const success = toaster.success
export const error = toaster.error
export const info = toaster.info
export const warn = toaster.warn
export const neutral = toaster.neutral
```

Instead of having to go through every file, the simplest solution was to create a _higher order function_. Doing this allowed us to "reverse" the roles so that instead of us searching through files, the toasts were instead _directed to our higher order function_.

This way the codes in the files were _not_ modified or _touched_. They still function as normal, and we gained the ability to remove duplicate toasts without going anywhere to write unnecessary code in the end. _This saved time_.

## 3. They Give The Ability To Create "_Private Worlds_"

![higher order functions can create private worlds](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/7-ways-higher-order-functions-can-improve-your-life/3.jpg)

What do I mean by "private worlds"?

Well, consider this example:

```jsx
const preparePeopleWithFavoriteColor = (color) => {
  const _people = []

  return {
    getPeople() {
      return _people
    },
    addPeople(people) {
      _people.push(...people)
    },
    addPerson(person) {
      _people.push(person)
    },
    gather(people) {
      if (Array.isArray(people)) {
        people.forEach((person) => {
          if (color === person.favoriteColor) {
            _people.push(person)
          }
        })
      }
    },
  }
}

const peopleWhoLoveRed = preparePeopleWithFavoriteColor('red')

axios
  .get('https://someapi.com/peoples')
  .then((response) => {
    const people = response.data.result

    if (people.length) {
      peopleWhoLoveRed.gather(people)
    }

    return axios
      .get('https://someapi.com/other-peoples')
      .then((response) => {
        const morePeople = response.data.result
        if (morePeople.length) {
          everyoneWhoLovesRed.gather(morePeople)
        }
        return
      })
      .then(() => {
        // finally, add me last because i love red too
        peopleWhoLoveRed.addPerson({
          nickName: 'jsmanifest',
          favoriteColor: 'red',
        })

        return axios.post('https://api.redlovers.com/v1/subscribers/', {
          people: peopleWhoLoveRed.getPeople(),
        })
      })
  })
  .catch((error) => {
    console.error(error)
  })
```

In the snippet, _preparePeopleWithFavoriteColor_ creates a _private world_ inside its block when called before returning the next function back to the caller. This "private world" is free of polluting the outer scope with clashing namecases and keeps its own _private_ variables and values.

In addition, it creates its _own interface and local api_ to manage its _people_ list. The scope outside will _never_ know what happens inside--and the only way for them to do so depends on the public methods that it returns.

And if you're sneaky enough, you can sneak in a secret API call in these cute little blocks to send you the list of people who love red everytime the code runs--and users will not even be able to tell because it didn't affect anything else in the app.

## 4. They Can Be Used As Quick And Hacky Solutions, Temporarily Decreasing Pressure

In the most darkest times, higher order functions can often save your life as it can be the quickest way to solve code issues without any noticeable changes in your app.

I once had a problem where users somehow still saw a "Dashboard" button in their navigation bar even _after_ they signed out in our react app. The dashboard button should have only been visible if the app detects that they were already logged in. When they click on the dashboard button, they get redirected to their user dashboard page.

At the time, the way that they signed out was to head over to their profile page and click the log out button. When the button was clicked, they should have been logged out completely and get redirected back to the signin page.

But _why_ was the _dashboard_ button still showing in the navigation bar? The user signed out, and when I debugged the issue, everything in the client including the local storage was cleared out as it should have--or so I thought.

I then realized that the issue was some parts of the _redux state_ was still there. The _redirection_ was using a _navigate_ that was optimized to redirect the user to a different route _without refreshing the whole page_. This caused caching issues.

So how would I then make sure that the entire state in redux resets after the user logs out?

Upon logging out we have redux dispatching an action creator with the action type _LOGOUT_ which should signal to the app that the user is logging out.

My immediate focus to providing a solution was modifying the action creator somehow. It seemed like the best spot to provide that enhancement.

And then I realized that it wasn't the best solution, because there was a _better_ solution: use a _higher order function_ (but _not_ here).

Here is a great example of why higher order functions are so _powerful_ in JavaScript:

Our root reducer file in `src/reducers/index.js` exported this:

```jsx
export default combineReducers({
  app,
  form: formReducer,
})
```

We then applied a _higher order function_ to instead wrap this and applied a _reset state_ logic whenever it detects that an action with type _LOGOUT_ is dispatched:

```jsx
const appReducer = combineReducers({
  app,
  form: formReducer,
})

// Higher order reducer that resets the redux state when we dispatch a logout action
const rootReducer = (state, action) => {
  if (['LOGOUT'].includes(action.type)) {
    state = undefined
  }
  return appReducer(state, action)
}

export default rootReducer
```

This resets the state back to its initial state because we re-assigned state to _undefined_. [Redux will call the reducer with an undefined state and returns the initial state of the app](https://redux.js.org/basics/reducers#handling-actions).

## 5. It Can Hold, Manipulate, And Pass The Manipulated Data Anywhere, Giving You An Easy Time Testing Different Solutions

![higher order functions can help manipulate and pass data around](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/7-ways-higher-order-functions-can-improve-your-life/4.jpg)

One of the coolest things you can do with higher order functions is keeping a private cache of data, manipulating it and passing it _anywhere_ in the app as you please. None of it will get tampered with from the outside.

For example, if you wanted to find a place to store access tokens so that when the token expires within 30 minutes in the middle of the user's session, you can refresh that token and re-set it for further use:

```jsx
const Api = function(params) {
  const _store_ = {
    accessToken: null,
  }

  return {
    getAccessToken() {
      return _store.accessToken
    },
    async login() {
      try {
        const response = await axios.post(
          'https://something.com/v1/auth',
          params,
        )
        return response.data
      } catch (error) {
        throw error
      }
    },
    async refreshToken() {
      try {
        const response = await axios.post(
          'https://something.com/v1/access_token/',
          params,
        )
        const { token } = response.data
        _store.accessToken = token
        return token
      } catch (error) {
        throw error
      }
    },
    setAccessToken(token) {
      if (token === undefined) {
        throw new Error('token is undefined')
      }
      _store.accessToken = token
    },
    // ...other methods
  }
}

const api = Api({
  username: 'bob',
  password: 'the_builder123',
})

api
  .refreshToken())
  .then((token) => console.log(token))
  .catch(console.error)
```

## 6. It Gives You The Ability To Create New Versions Of Something

Lets say you decided to create an RPG game to hand over to your 4 old nephew as an attempt to keep him from bugging you every day. In this game you decided you want to create a batch of warriors:

```jsx
const characters = []

const Warrior = function createWarrior(name) {
  this.name = name
  this.hp = 100
  this.mp = 100
  this.defence = 60

  return {
    // Slash the enemy, decreasing their hp down by 35
    slash(target) {
      target.hp -= 35
      return target
    },
    // Increases the warrior's defence by 100 for 40 seconds.
    // Each second will decrement their defence by 1 as the time runs out.
    battleCry() {
      this.defence += 100
      this.battleCryInterval = setInterval(() => {
        this.defence -= 1
      }, 1000)
      this.battleCryTimeout = setTimeout(() => {
        this.defence = 60
      }, 40000)
    },
  }
}
```

You can create a _higher order function_ that first accepts a list of names to create the warriors for, then returns a new function that helps create the warriors:

```jsx
const massCreateWarriors = function(names) {
  return (onCreate) => {
    const warriors = []
    names.forEach((name) => {
      const newWarrior = new Warrior(name)
      if (onCreate) onCreate(newWarrior)
      warriors.push(newWarrior)
    })
    return warriors
  }
}

const prepareWarriors = massCreateWarriors(['bob', 'joe', 'sally', 'woodie'])

const newWarriors = prepareWarriors(function onCreate(newWarrior) {
  if (newWarrior.name === 'sally') {
    newWarrior.theme = 'red'
  }
  characters.push(newWarrior)
})
```

Isn't it nice to just create a helper function to create a mass amount of characters for you, instead of having to hard code that every time for different characters?

## 7. It Can Help You Develop A Healthy Relationship With Your Boss And Your Co-workers

![higher order functions can help you develop a healthy relationship with your boss and co workers](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/7-ways-higher-order-functions-can-improve-your-life/5.jpg)

Higher order functions can help solve many problems. With that said, with the many useful benefits that higher order functions can bring to the table like code size reduction and re-usability, you will decrease the likelihood of stressing over people around you when used that way. Your co-workers will love that you are not just a developer, but a developer that strives to do great things. In addition, you also \*increase\* the likelihood that newer developers can learn off your code to help them improve their skills. This makes you highly valuable to the team, the boss, and the company as a whole.

... _and when your coworkers are happy, they'll most likely be in the mood to bring in free donuts_.

## Conclusion

And this concludes the end of the post! I hope you enjoyed it and look out for more posts from me in the future! Find me on [medium](https://medium.com/@jsmanifest)

Happy friday!