ES6 Module system 😃

ES6 modules are one of the more critically important concepts you will come across in every React program. I will not delve in-depth as to why the module patterns is important. You can read more about that here, here and here. Instead I will provide a quick overview of what they are and how to quickly get started with them.

Instead I will provide a quick overview of what they are and how to quickly get started with them.

The word “modules” refers to a small units of independent reusable code. They are the foundation of many design patterns and are necessary to build any substantially complex application.

Let’s look at building a computer for example, it consists of several parts, but you could just assemble each part without worrying about the engineering complexities behind each component or having to create your own components everytime. As Software Engineers we usually have to re-use codes either written by others or by ourselves without having to reinvent the wheel all the time.

The module you are exporting could be any reusable block of code. It could be a simple variable, a function , a react component, a class, a third party module you modified etc. Let’s create simple modules and understand how we can export them.ES6 provides two ways to export a module from a file: named export and default export.

Let’s create some modules in a file named myModules.js

Ignore the implementation details if you are not sure how the code works. This is one major point of using third party modules. The implementation or how it works is less important. Just know what it does and how to use it.

// myModules.js
const moduleConst = {title: "I am a module CONST"}

// this function takes an array and add all the numbers
const addNumberInArray = (array) => array.reduce((a, b) => a + b);

// this function takes an array and finds the average
const findArrayAverage = (array) => array.reduce((a, b) => a + b / array.length)
}

Now that we have created our module, let’s make them accessible to other parts of our code by “exporting” them.

With named exports, one can have multiple named exports per file. Then import the specific modules surrounded in braces. The name of imported module has to be the same as the name of the exported module.

// myModules.js

// individually exported
exports const moduleConst = {title: "I am a module CONST"}

// exports just this function individually
export const addNumberInArray = (array) => array.reduce((a, b) => a + b);

// exports just this function individually
export const findArrayAverage = (array) => array.reduce((a, b) => a + b / array.length)
}

But that looks cumbersome and repetitive. Is there a better way?, Sure!

// myModules.js
const moduleConst = {title: "I am a module comment"}

// this function takes an array and add all the numbers
const addNumberInArray = (array) => array.reduce((a, b) => a + b);

// this function takes an array finds the average
const findArrayAverage = (array) => array.reduce((a, b) => a + b / array.length)
}

export {moduleConst, addNumberInArray, findArrayAverage }

You can only have one default export per file. When the default export is imported we can then specify any name for it

// myModules.js

// named export
export const moduleConst = {title: "I am a module comment"}

// named export
export const addNumberInArray = (array) => array.reduce((a, b) => a + b);

// this is the default export only 1 is allowed in this file
export default const findArrayAverage = (array) => array.reduce((a, b) => a + b / array.length)
}

You can give the exported module an alias(like a nickname), usually because you prefer a shorter name. For example the addNumberInArray and findArrayAverage could be exported with an alias like so:

export {moduleConst, addNumberInArray as add, findArrayAverage as avg }

In summary from documentation :

Named exports are useful to export several values from within the same file. While importing, one will simply refer to the exported value by the same name.

Default export allows just a single default export per module.You can of course have several other named exports within the same file. The default export is considered the main exported value. A default export can be a function, a class, an object or anything else.

Now that we understand how to export modules, let’s look at importing them and using them. Importing is quite straightforward with the import keyword. Importing from myModules.js will look like so:

//app.js

import {moduleConst,addNumberInArray, findArrayAverage } from './myModules.js' //

// You can also import with an alias here if you didn't export with an alias
import {moduleConst, addNumberInArray as add, findArrayAverage as avg } from './myModules.js'

You can import everything that is exported from a module like this:

//app.js

import * as All from './myModules.js'

// this allows us to have access to every member of the module with the dot notation.Like so:

All.moduleConst
All.addNumberInArray() // since this is a function we have to call it.
All.findArrayAverage()

When you import a default export , you simply use the import keyword to import the module like we’ve been doing. The only major difference is that you could call the import whatever name you wish. For example:

//  myModules.js

export const moduleConst = {title: "I am a module comment"}

export const addNumberInArray = (array) => array.reduce((a, b) => a + b);

// this is the default export!!!
export default const findArrayAverage = (array) => array.reduce((a, b) => a + b / array.length)

//  app.js

// all the below 3 will be referencing the `findArrayAverage` module since it is the only default export in myModules.js
import abrcadabra from  './myModules.js'
import someMagic from './myModules.js'
import findArrayAverage from './myModules.js'

Remember, the main purpose of a module is to have a reusable piece of code.The piece of code exposes an API to us that we can then use without having to ever understand the implementation details of the code itself. Let’s start with the simple examples from myModules. Let’s assume you have to calculate the average/sum of an array many times within your code.You could simply import myModules.js to perform the operation.Let’s pretend these are even more complex algorithmic computations and you do not want to or cannot write the functions yourself. You can simply import the module and use them in your code like so:

//app.js
import {addNumberInArray, findArrayAverage } from './myModules.js'

const array = [1,2,3,4,5]
// I need to calculate sum of an array using the addNumberInArray function from './myModules.js'.
// Simply pass the array to the function like so:
addNumberInArray(array) //> returns the sum which is 15

// I need to calculate average of an array using the findArrayAverage function from './myModules.js'.
// Simply pass the array to the function like so:
findArrayAverage(array) //> returns the sum which is 3.8

Let’s look at more interesting example from react-router-dom.

We imported React from react library. Then imported BrowserRouter , Route, and Link from react-router-dom.

Note: BrowserRouter has been imported with an alias Router, this is much shorter to reference throughout the code than the longer BrowserRouter.

//app.js

import React from "react";  // we import React from the react library
import { BrowserRouter as Router, Route, Link } from "react-router-dom" import the modules we need from the `react-router-dom`
function AppRouter() {
 return (
   <Router> // we then use the imported `Router` here
     <div>
       <nav>
         <ul>
           <li>
             <Link to="/">Home</Link> // making use of the imported `Link`
           </li>
           <li>
             <Link to="/about/">About</Link>
           </li>
           <li>
             <Link to="/users/">Users</Link>
           </li>
         </ul>
       </nav>
       <Route path="/" exact component={Index} />  //making use of the imported `Link`
       <Route path="/about/" component={About} />
       <Route path="/users/" component={Users} />
     </div>
   </Router>
 );
}
export default AppRouter;