when i export a class as 'export default AvatarStore;' versus 'export default new AvatarStore();' i get the following error trying to use its methods in other classes... Is using the new syntax correct?
here is the code:
import { List } from 'immutable';
import EventEmitter from 'events';
import Utils from '../utils/Utils.js'
import RestService from '../services/RestService'
import RestCallStatus from '../constants/RestCallStatus'
import Avatar from '../models/Avatar'
const CHANGE_EVENT = 'change';
const TAG = 'AvatarStore';
class AvatarStore extends EventEmitter {
constructor() {
super();
this._populateRestCallStatus = RestCallStatus.NOT_REQUESTED;
this._populated = false;
this._dataStore = List();
}
populate(){
RestService.getAllAvatars(this.handleSuccess.bind(this), this.handleFailure.bind(this));
this._populateRestCallStatus = RestCallStatus.STARTED
}
handleSuccess(serviceName, jsonData){
Utils.logMethod(TAG, 'handleSuccess ' + serviceName);
if(jsonData.length > 0){ this._dataStore = List().clear(); }
jsonData.forEach((entity) => {
this._dataStore = this._dataStore.push(new Avatar(entity))
});
this._populated = true;
this._populateRestCallStatus = RestCallStatus.SUCCESS;
this.emitChange();
}
handleFailure(serviceName, error){
Utils.logMethod(TAG, 'handleFailure');
this._populateRestCallStatus = RestCallStatus.FAILED
console.error(`Server call ${serviceName} failed with error: ${serviceName}!`)
}
getItems(){
//Utils.logMethod(TAG, 'getItems');
return this._dataStore;
}
getItemById(itemId){
return Utils.findArrayElementById(this._dataStore, itemId);
}
getPopulated(){
return this._populated;
}
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
}
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
emitChange() {
Utils.logMethod(TAG, 'emitChange');
this.emit(CHANGE_EVENT);
}
}
export default new AvatarStore();
export default AvatarStore means that you want to export class. in export default new AvatarStore() case, you export instance of class (object). So you need to use the one it makes sense in your case - use the first if you want to have more instances of AvatarStore, otherwise you can use the second one.
Of course in the first case you need to make new instance somewhere after you import it.
Related
I was trying to implement a Builder pattern in Javascript using modularity, where I got caught in a circular dependencies-like situation. My file structure looks something like this,
index.js
import PersonBuilder from "./PersonBuilder.js";
let pb = new PersonBuilder();
let person = pb.lives.in('jaipur').at('ajmer Road')
.age.of(32).build();
Person.js
class Person
{
constructor()
{
this.city = this.street = this.name = "";
this.age = 0;
}
toString(){
return `${this.name} from ${this.city} lives at ${this.street} is ${this.age} years old`;
}
}
export default Person;
PersonBuilder.js
import Person from "./Person.js";
import PersonAgeBuilder from "./PersonAgeBuilder.js";
import PersonAddressBuilder from "./PersonAddressBuilder.js";
class PersonBuilder
{
constructor(person = new Person)
{
this.Person = person;
}
get lives()
{
return new PersonAddressBuilder(this.person);
}
get age()
{
return new PersonAgeBuilder(this.person);
}
build()
{
return this.person;
}
}
export default PersonBuilder;
PersonAddressBuilder.js
import PersonBuilder from "./PersonBuilder.js";
class PersonAddressBuilder extends PersonBuilder
{
constructor(person)
{
super(person);
}
in(city){
this.person.city = city;
return this;
}
at(street)
{
this.person.street = street;
return this;
}
}
export default PersonAddressBuilder;
PersonAgeBuilder.js
import PersonBuilder from "./PersonBuilder.js";
class PersonAgeBuilder extends PersonBuilder
{
constructor(person)
{
super(person);
}
of(age){
this.person.age = age;
}
}
export default PersonAgeBuilder;
When I am calling index.js on my browser I got the following error:
Uncaught ReferenceError: Cannot access 'PersonBuilder' before initialization
at PersonAgeBuilder.js:4
how can I solve this?
I have declared a class, like:
export default class Utils {
static deepClone(): object {
return {}
}
}
so when I want to use deepClone, I can:
// First One
import Utils from './Utils';
export default class Element {
constructor(){
this.utils = new Utils()
}
create(){
return this.utils.deepClone()
}
}
or:
// Second One
import Utils from './Utils';
export default class Element {
constructor(){
this.utils = Utils
// this is an optional
// in my child class I need't to import Utils
// I can use this.utils.deepClone() directly
}
create(){
return Utils.deepClone()
}
}
I wonder which is a better way to imply Element class
Looking forward to your reply, I can’t thank you enough
The second way is more correct but it has a problem that you should create an instance of Utils class to use each property which isn't a static method.
The output of a class that you didn't create an instance is a function instead of an object of prototypes.
./Utils.js
export default class Utils {
static deepClone(): object {
return {}
}
public deepExtend() {
// deepClone code
}
}
Use in another file:
import Utils from './Utils';
export default class Element {
constructor(){
this.utils = new Utils();
}
create(){
return Utils.deepClone()
}
extend(){
return this.utils.deepExtend()
}
}
I would return export new of the Utils and I will pass it in the constructor of your Element as an Instance, something like:
IUtils = someInterface;
export default class Element {
constructor(utils: IUtils){
this.utils = utils;
}
create(){
return this.utils.deepClone()
}
}
In these way it:
Doesn't create new instances for nothing
Uses other instances that you can pass to your Element class
Is testable
I have some code on react that should re-render the main page when I click. but it does not work. Can someone suggest an idea?
/store/index.js
import jsonObjects from './jsonObjects';
class RootStore {
constructor() {
this.jsonObjects = new jsonObjects(this);
}
}
export default RootStore;
/store/jsonObjects.js
import sciences from '../data/sciences.json'
class JsonObjects {
jsonObjectsList = observable(JSON.parse(sciences))
get jsonObjects() {
return this.jsonObjectsList.filter(jsonObjects => jsonObjects.deleted === false);
}
handleClick() {}
}
decorate(JsonObjects, {
handleClick: action,
jsonObjects: computed
})
export default JsonObjects;
in index.js I have.
import PageLoader from './pageLoader';
$(function() {
const pageLoader = new PageLoader();
});
and pageloader.js
class PageLoader{
constructor(){
{
this.customer = null;
this.data = [];
this.init();
}
}
init() { }
}
module.exports = PageLoader;
everything works fine. but if I import a class from page loader.
import Customer from './customer';
class PageLoader{
constructor(){
{
this.customer = null;
this.data = [];
this.init();
}
}
init() { }
}
module.exports = PageLoader;
and customer.js
class Customer{
constructor(){
this.data = [];
this.init();
}
init() {
}
}
module.exports = Customer;
I receive
WARNING in ./src/index.js 10:23-33 "export 'default' (imported as
'PageLoader') was not found in './pageLoader'
module.exports
syntax is from Modules (which are largely used in NodeJs - the counterpart of it is require rather than import). If you want to use import, you need to use export clause, which is from es6 modules
export default PageLoader
you could also do named exports
export { PageLoader };
and then
import { PageLoader } from './pageLoader';
Further reading
I have a file called searchBar.ts in which contains a init() function that I wish to call in a file called index.ts.
My searchBar.ts file looks like this:
class searchBar {
init() {
console.log('work you C*&*T')
}
}
export let searchBarClass = new searchBar;
I then want to be able to call this function in index.ts. I am currently trying to do this with the below code but init is never found with my intellisense:
import { searchBarClass } from './modules/searchBar';
class Main {
searchBarClass.init()
}
let main = new Main();
export {main}
Later on I then want to wrap the function in a global function that I'll call in the HTML file.
Let me know your thoughts
If you want to export a class and call the init() method on the object instance:
export class SearchBar {
init() {
console.log('work you C*&*T')
}
}
Then accessing it from another file:
import { SearchBar } from './modules/searchBar';
export class Main {
constructor() {
let searchBar = new SearchBar();
searchBar.init();
}
}
let main = new Main();
If you want to access the init() function statically:
export class SearchBar {
static init() {
console.log('work you C*&*T')
}
}
Then accessing it from another file:
import { SearchBar } from './modules/searchBar';
export class Main {
constructor() {
SearchBar.init();
}
}
let main = new Main();