Store values in esmodules
Tags: javascript, esmodules, closures
Published: 2020-06-22 17:42:50

ECMAScript modules its present in every modern browsers today, we can use it to do a lot of tasks, like distributing our reusable code between files and import as they are needed.

## Import and execute

You can import a file with modules and then execute  without the need of a value in the return of the import.

This will just execute the module.

**index.html**
``` html
<!DOCTYPE html>
<html lang="en">
<meta charset=utf-8>
<title>Module execution</title>

<script type="module" src="./module-execution.js"></script>
<p>This is a valid HTML Markup!</p>
```

**module.js**
``` javascript
import './printHello.js';
```

**printHello.js**
``` javascript
console.log('Hello :D');
```

This example will not working running by just opening the html in your browser, you need to run a server to allow the browser to get the esmodules.

There are simple ways to running a server locally, my go to choice is using npx serve, if you have the **npm** 5.2 or greater, you can open the terminal and type `npx serve`, it'll start a local server for you.

Notice that you need to add the file extension to a module to import at `import './printHello.js;`.
It won't work if you don't add the file extension.

This is an utter useless use of esmodules, but serves the purpose of showing how you can execute javascript from an external module, cool 🧐.

## Import values

With esmodules, the most important thing that you can do, its import values (booleans, numbers, strings, arrays, objects, function, and others).

See the example bellow

**index.html**
``` html
<!DOCTYPE html>
<html lang="en">
<meta charset=utf-8>
<title>Module values</title>

<script type="module" src="./module-value.js"></script>
```

**module-value.js**
``` javascript
import changeMyValue, { myValue } from './my-value.js';

// Save the value from my-value.js
const oldValue = myValue;

changeMyValue();

// Save the updated value from my-value.js
const newValue = myValue;

// Display values for comparison
console.log({
  oldValue, // false
  newValue  // true
});
```

**my-value.js**
``` javascript
let myValue = false

function changeMyValue() {
  myValue = true
};

/**
 * Note:
 * Don't export default your value
 * It'll create a new instance of it
 * And not update :(
 * 
 * But that is cool, because we know it now!
 * */
export { myValue };
export default changeMyValue;
```

This is other sample (thus have not much utility, besides learning), but here are some new things!

You can see that in the first line from `module-value.js` the import syntax its calling specific values!

There is other new thing, you are changing the value from a variable from other module using an exported function. This gave me the idea, that we can store values in memory using esmodules, and import the data as we please! This example will not do much good to your code, but it shows how to use export, export default and import and destructuring imports.

Let's go to the main focus now!

## Store values in memory with esmodules

Now the example can get a little bit trickier, here the simplest example that I could imagine for values in esmodules.

**index.html**
``` html
<!DOCTYPE html>
<html lang="en">
<meta charset=utf-8>
<title>Module store! Finally!</title>

<script type="module" src="./module-store.js"></script>
```

**module-store.js**
``` javascript
import { addSecretNumber } from './store-value.js';
import useSecretNumberFromOtherModule from './use-store.js';

useSecretNumberFromOtherModule();
// return: [ 2, 7, 6, 9, 5, 1, 4, 3 ];

addSecretNumber(8);
// Add 8 to secret number

useSecretNumberFromOtherModule();
// return: [ 2, 7, 6, 9, 5, 1, 4, 3, 8 ];

addSecretNumber('Not a number, but that is ok');
// Spoiling the perfect numbers array :(

useSecretNumberFromOtherModule();
// return: [ 2, 7, 6, 9, 5, 1, 4, 3, 8, 'Not a number, but that is ok' ];
```

**store-value.js**
``` javascript
const secretNumber = [ 2, 7, 6, 9, 5, 1, 4, 3 ];

function addSecretNumber(number) {
  secretNumber.push(number);
}
 
export { secretNumber, addSecretNumber };
```

**use-store.js**
``` javascript
import { secretNumber } from './store-value.js';

function useSecretNumberFromOtherModule() {
  console.log(secretNumber);
};

export default useSecretNumberFromOtherModule;
```

Here we are! Storing values in a module! But wait, let's go step by step and understand what is happening.

1. First you need to create a storage in order to use it, you can see that the file `store-value.js` its doing it. We are basically using the power of closures to do it.

We created an value:
``` javascript
const secretNumber = [ 2, 7, 6, 9, 5, 1, 4, 3 ];
```

We created a function to change the stored value:
``` javascript
function addSecretNumber(number) {
  secretNumber.push(number);
}
```

And exported the value and the function to update the value.
``` javascript
export { secretNumber, addSecretNumber };
```

This file it's the core of storage, the rest of the code its just an example of using it.

Remember: If we export our value as default, it'll not update with our function. It'll export a new instance of this value.

Remember II: You can export default arrays and object, because JavaScript is a very unique programming language and would create a new instance of the array or object, but not the values inside these values, but I would not recommend anyway. To learn more, go to [Just JavaScript](https://justjavascript.com/), a great way to learn how to create a mental model to understand deeply javascript from (Dan Abramov)[https://twitter.com/dan_abramov].

2. To use a stored variable, import from the file you created to store.

When you want to use the stored variable, have to import your value, in our example we are importing the value inside the constant `secretNumber`.
``` javascript
import { secretNumber } from './store-value.js';
```

And that's it! Very easy and simple.

3. The complex part: Updating the value.
To update, you have to use a function that you created in your storage, in our case it was `addSecretNumber`, that have one parameter and add one item to the array inside the constant secretNumber.

``` javascript
import { addSecretNumber } from './store-value.js';
```

After you updated the value of `secretNumber` using the function `addSecretNumber`, when you look for the variable `secretNumber` next time, it'll have the updated value. Cool.


## Warning

There is a important subject to be **REALLY CAREFUL** about using esmodules to store values.

1. If you change, it'll change his value for every other file that would want to use the value from the store that you created.

2. The original value does not come back, unless you specifically create a function to do it! The value its just a simple way to store data to use later.

3. If you use this to update DOM elements, it will not do it alone, this is not a framework or library.

4. Have fun and break your code from time to time!

---

This post was inspired after I tried esmodules in browser doing a calculator like [Numi](https://numi.app/) for the browser.

### [Math Notes](https://imaginamundo.github.io/math-notes/)
My calculator for the browser. You can see the details about how I used esmodules to store values that I needed later.