How To Fix the “this.activateMode is not a function” Error in Gutenberg

Imagine you are busy developing a Gutenberg block. You reload the page, and suddenly the editor will break, displaying an The editor has encountered an unexpected error. message. You look into the JavaScript console of your browser, and see a this.activateMode is not a function error. 

What is the error cause?

On the screenshot above, you can see that the stack trace includes references to /wp-includes/js/media-views.min.js. Searching for the this.activeMode string inside of WordPress’ media code, we find this occurrence:

_createModes: function() {
   // Store active "modes" that the frame is in. Unrelated to region modes.
this.activeModes = new Backbone.Collection();
   this.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );

   _.each( this.options.mode, function( mode ) {
      this.activateMode( mode );
   }, this );
},

The _ in this snippet is the entry point of Underscore.js, a helper library that ships with WordPress.

However looking further into the error message above, it contains two functions names: forEach and arrayEach.

Searching through the codebase, we find that these functions are part of Lodash, a helper library used by Gutenberg.

function forEach(collection, iteratee) {
  var func = isArray(collection) ? arrayEach : baseEach;
  return func(collection, getIteratee(iteratee, 3));
}
function arrayEach(array, iteratee) {
  var index = -1,
      length = array == null ? 0 : array.length;
  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
        break;
    }
  }
  return array;
}

Both Underscores and Lodash use _ to expose their API. When Gutenberg is loaded, Lodash overwrites the _ global variable used by Underscore. 

The two libraries include a _.each() function. But the signature is different, as Lodash’s implementation does not support the content argument:

  • Underscore: _.each(obj, iteratee, context)
  • Lodash: _.each(collection, iteratee)

This means that in this snippet from WordPress media code, the this variable is not passed along, which leads to a fatal error:

_.each( this.options.mode, function( mode ) {
      this.activateMode( mode );
   }, this );

How to fix the error?

When you are using Webpack and Babel to build the JavaScript in your Gutenberg blocks you need to  add babel-plugin-lodash as an NPM dependency. Then add an entry to your project’s  .babelrc as described in the plugin’s documentation.

This will modify the way that Lodash dependencies are included. _.each() would be transformed to _each(), therefore avoiding overwriting any of WordPress’ JavaScript globals.

If you are not using a build pipeline, and are writing your blocks in plain JavaScript, make sure to enable the no conflict mode of Lodash when enqueuing the script:

wp_enqueue_script( 'lodash', '...' );
wp_add_inline_script( 'lodash', 'window.lodash = _.noConflict();', 'after' );

Alternatively, you can also use the version packaged with Gutenberg itself, as it is enqueued in no conflict mode.

Conclusion

This guide should have helped you resolve the issue of Gutenberg breaking.

If you’re not yet familiar with developing custom Gutenberg blocks, consider reading this guide for learning Gutenberg development in 6 days.

Is there a development task that you struggle with? Do you want to know more about a particular WordPress API?

If so, please let me know by suggesting a topic for an article.