[SalesForce] Feasibility to import entire LWC classes to access @api methods

I'm looking to modularize my LWC without having to embed them in the template. Ideally, would this kind of pattern be feasible? I'm not sure if it's my lack of ES6 knowledge (modules) or that LWC blocks this but this is what I'm attempting:

UtilityLWC.js

import { LightningElement, api } from 'lwc';

export default class UtilityLWC extends LightningElement {

  @api
  foo() {
    console.log('foo from UtilityLWC');
  }

  @api
  bar() {
    console.log('bar from UtilityLWC');
  }

}

ConsumerLWC.js


import { LightningElement, api, track, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import UtilityLWC from 'c/UtilityLWC'; // doesn't work
// import * as util from c/UtilityLWC; // also doesn't work
// import { foo, bar } from c/UtilityLWC; // nope

export default class ConsumerLWC extends NavigationMixin(LightningElement) {

  connectedCallback() {
    // None of these work
    UtilityLWC.foo();
    UtilityLWC.bar();
    // util.foo();
    // util.bar();
    // foo();
    // bar();
  }

}

So the easy way out is to add <c:utilityLWC> inside ConsumerLWC.html and use standard querySelector to reach inside an call foo() / bar() but is that the only way to do this?

Edit: I am aware of the general JS code re-use patterns (example in my lwc-utils repo). This is more a question of, is it possible to have that kind of pattern but also, for example, have reusable wires?

Best Answer

I am not ES6+ or JS expert, but there's a section for this on the documentation - Share JavaScript Code and also there are examples on lwc-recipe for this. In general, the export works as documented for ES6 module.

From LWC documentation:

A module can export a single default function or variable.

A module can also export named functions or variables.

So it doesn't seem that you can actually export the whole class. You will need to modify your shared JS based on the approach as mentioned in the documentation, i.e., you will need to export the functions as named functions. For further details, refer to the links mentioned above.


As a quick example, below is an approach for exporting and using a named function.

Let's say I have a shared JS as below:

sharedJS.js

const mySharedHelloWorld = () => {
     return 'Hello Shared World!'; 
}

export {mySharedHelloWorld};

And that I want to use this on another component, I will go doing as below in the component.

helloWorldJS.js

import { mySharedHelloWorld} from 'c/sharedJS';

export default class MyHelloWorld extends LightningElement {

    myHelloWorld = mySharedHelloWorld();
}

helloWorld.html

{myHelloWorld}
Related Topic