3

In my react application, I want to use a library (money.js) in 2 components which have different settings.

This library:
http://openexchangerates.github.io/money.js/
http://openexchangerates.github.io/money.js/money.js

I checked that javascript is using reference so the 2 components are actually referencing the same thing.

Does import create a new copy of imported library?

ES6 variable import by reference or copy

Is that possible without changing the source code (ideally), I can do something like the following

// a.js
import fx from 'money'
fx.rates={USD:1, EUR: 2.001}

// b.js
import fx from 'money'
fx.rates={USD:1, EUR: 2.002}

In my situation, I noticed that changing the rates in b.js, it also affect a.js.

Sh. Pavel
  • 1,584
  • 15
  • 28
pk028382
  • 95
  • 1
  • 10
  • 1
    A great explanation of the JS module ecosystem can be found here - https://medium.freecodecamp.org/javascript-modules-a-beginner-s-guide-783f7d7a5fcc. Since ES6 modules are live and read-only copies, you have to maintain your "rates" or whatever module specific config in another jS object ( service if you may ). Just use the utilities provided my your specific library in the service thus created. Hope this help ! – Shobhit Chittora Jun 27 '18 at 08:27
  • Possible duplicate of [How do I correctly clone a JavaScript object?](https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object) – Amanshu Kataria Jun 27 '18 at 08:44
  • 1
    @AmanshuKataria - No, modules are much more complicated than simple objects. – T.J. Crowder Jun 27 '18 at 12:57
  • @ShobhitChittora - ES2015 modules aren't read-only. They *are* shared. – T.J. Crowder Jun 27 '18 at 12:57

5 Answers5

3

No, there's no general one-size-fits-all way to clone a module or load separate copies of it. You may be able to do it, but it will be dependent on the specific way the module is coded.

It's unfortunate that the library you're using doesn't have the concept of an instance rather than making everything global to the library. You might consider adding that concept to the library and sending the original repo a pull request (if they decline it, you can always create a fork).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks. I think I am going to just use an extra variable to store and restore the rates whenever I want to use fx – pk028382 Jun 27 '18 at 11:55
1

You can do it simply by adding query-param to module filepath:

// a.js
import fx from 'money?first'
fx.rates={USD:1, EUR: 2.001}

// b.js
import fx from 'money?second'
fx.rates={USD:1, EUR: 2.002}
Kchaiene
  • 11
  • 1
  • oh my sweet Lord, why is no one voting for this answer. Thank youuuu so much. you really made my day. thank you thank you – Jacky Supit Jun 07 '22 at 12:51
0

you can clone that rates object in each file :-

var localRatesVariable = Object.assign({}, fx.rates);

  • This isn't a deep clone. Each by-reference property will be pointed to the same in the original object. – Shanimal May 28 '21 at 22:53
0

Modules are evaluated once, that's one of their main properties. It's possible to re-evaluate a module in some environment that supports it (Node.js) but not in client-side application.

In this case the library is hard-coded to use fx.rates object. Even if it's copied, it will continue to use it.

A proper way is to modify library source code to support multiple instances.

An alternative is to create a wrapper that hacks the library to behave like expected. Considering that it's convert method that uses fx.rates and it's synchronous, it can be patched to swap rates property during a call:

import fx from 'money'

export default function fxFactory(rates) {
  return Object.assign({}, fx, {
    convert(...args) {
      let convertResult;
      const ratesOriginal = fx.rates;
      try {
        fx.rates = rates;
        convertResult = fx.convert(...args);
      } finally {
        fx.rates = ratesOriginal;
      }
      return convertResult;
    }
  });
}

// a.js
import fxFactory from './fx'
const rates={USD:1, EUR: 2.001};
const fx1 = fxFactory(rates);
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
0

You can deep copy object:

let localRatesVariable = JSON.parse(JSON.stringify(fx.rates));
Ali Rehman
  • 3,731
  • 4
  • 23
  • 28