Javascript exporting class instance (React JS application) - javascript

I am building a single page application using React JS, and following the Flux flow.
I have a problem where I want to export an instance of a class (an action class), import elsewhere, and then reference some of the class methods. I can import the class with no error, but when the class' methods are referenced it throws a "TypeError: undefined is not an object".
A console.log() confirms that that class is undefined, however I also import the action in another file. So I decided to console log it's reference to the action class and log where the export is happening.
What I found is that the first reference is still undefined, but before the second reference is called, the export happens and the second console.log() returns the object and it's methods.
So my question is, does javascript deal with exports as it comes across them, or does it do all the exports first?
Example of the code:
class Action {
methodOne(){ ..... }
methodTwo(){ ..... }
}
const instance = new Action();
export default instance;
The action is then imported as:
import Action from '../actions/Action';
in the two files.
I have checked and double checked spelling and import paths which all seem to be correct. Some research does say that it could be something to do with circular references, though that doesn't seem to be obvious to me (not discounting it though).
I'm all out of ideas as to where the problem is.

Related

console.log not being called inside react-native constructor

Im really new to react and react-native and having problem with this really simple code below.
The code below is on a minimal react native app.
It renders the content inside the render method but looks dont executing the instructions inside the constructor, i havent the alert box neither the log appears in console.
I need ensure a variable is initialized just on application startup and it was my way to check it, im thinking about use a logic using Undefined and give up on using contructor.
Some related links i found:
constructor in React not being called upon component being instantiated
Console.Log Not Being Called Inside React Constructor
My code :
class TestComponent extends Component {
Constructor(props){
this.super(props);
console.log("CalingConstructorLog"); // do nothing
Alert.alert("CalingConstructorLog"); // do nothing
}
render() {
return (
<Text>It renders OK!</Text>
);
}
}
export default TestComponent;

undefined variables in javascript class

I'm having trouble running and understanding classes in javascript. I am experimenting this with a simple app that I made. The end goal of it is just to grab names from a textarea, store that in an array, and then perform actions on it such as displaying them to the screen or shuffling them. To do this, I made 2 classes. One for storing the names to an array and then another that extends from this class to manipulate the array - just for the sake of organization. Here's my code:
Store names to array
import $ from 'jquery';
class SaveInput {
// dom selection usually and firing events when a page loads.
constructor(){
this.mainText = $('.main-text');
this.names = [];
this.events();
}
//events to watch for such as click
events() {
// save names to array, no submit button
this.mainText.blur(this.saveNameIndex.bind(this));
}
// methods to be called from events
// save names without submitting
saveNameIndex() {
let namesResult = this.names = this.mainText.val().split('\n');
return namesResult;
}
}
export default SaveInput;
Maniuplate Array
import $ from 'jquery';
import SaveInput from './SaveInput';
class Display extends SaveInput {
// dom selection usually and firing events when a page loads.
constructor(names){
super(names);
this.h1= $('h1');
this.events();
}
//events to watch for such as click
events(){
this.h1.click(this.log.bind(this));
}
// methods to be called from events
//display images with names
log () {
console.log('test');
}
}
export default Display;
It doesn't matter what I do, as you can see from my 2nd class that I was just trying to test by click an h1 tag to console log some text. I always get the same error when the app loads:
App.js:10522 Uncaught TypeError: Cannot read property 'click' of undefined
at Display.events (App.js:10522)
at Display.SaveInput (App.js:96)
at new Display (App.js:10509)
at Object.defineProperty.value (App.js:10412)
at __webpack_require__ (App.js:20)
at Object.defineProperty.value (App.js:63)
at App.js:66
The only thing I want from the saveInput class is the names array so I can pass it on and there seems to be some conflict when I extend that class. What am I missing?
When you create a Display object, it first calls the base object's constructor. That SaveInput constructor calls this.events() which you have overridden in the derived Display class. That overridden implementation is expecting this.h1 to be set, but it isn't set yet, thus the error you see.
I don't really understand what you're trying to do here to know what fix to suggest, but this is a timing issue based on what happens in the constructor and what the derived class is ready for. Probably you should take some stuff out of the constructor so the object can get fully formed before you call this.events().
Also, if you expect the SaveInput version of events() to get called, you need to add super.events() to the Display implementation of events() so the base object's version gets called too.

How does an imported module get evaluated in ES6 exactly?

(There is another question of similar title out there but I have a different question here.)
It's stated that in ES6, an imported module is "executed" immediately. However, say for example I have exported an object:
let Player = {
player: null,
init(domId, playerId, onReady) {
window.onYouTubeIframeAPIReady = () => {
this.onIframeReady(domId, playerId, onReady)
}
},
...
}
export default Player
Apparently the object only contains properties and methods. Then, I import it in another module:
import Player from "./player"
How can a series of name-value pairs be "executed" though? To execute the constructor of a class when it's imported makes much more sense (is a class's constructor automatically run when it's imported though? I'm also confused on that), but to "execute" an object just doesn't make much sense to me.
Also, if I import a function from another module, does the function gets immediately "evaluated" and its result produced? This also doesn't seem very right to me since a function sometimes requires arguments, which the importing module doesn't automatically provide any.
Maybe I misunderstood the meaning of the word "execute"/"evaluate" here?

Importing through a module file gives undefined for first event queue

I've got a React project where I keep all components available through a single file, so instead of doing
import Foo from "./Foo.js"
import Bar from "./Bar.js"
I've got a components.js-file with
export Foo from "./Foo.js"
export Bar from "./Bar.js"
so I can do
import { Foo, Bar } from "./components.js"
My problem is that Foo, Bar, and anything else I import this way is undefined for the first "event queue", that is, if I have this file
import { Foo, Bar } from "./components.js"
console.log("FOO1", !!Foo, !!Bar)
window.setTimeout(() => {
console.log("FOO2", !!Foo, !!Bar)
}, 0)
it will output
FOO1 false false
FOO2 true true
This hasn't caused any trouble for with plain React components (functions nor classes), but when I try to use Redux's connect-function to create a container component, it complains about the input being undefined. I guess this is because when I declare React components, the references aren't, well, referenced directly, but when I call the connect-function, it immediately tries to access the component and sees that it's undefined. This is just my uneducated hypothesis though.
Why does this happen and how can I prevent it?
I thought it might've been a problem with the Stage 1 transform-export-extensions plugin, but I've used different syntax - e.g. export const Foo = require("./Foo").default - in components.js and the problem persists.

What qualifies as being a dynamic export in ES6

I hear that dynamic exports/imports are not allowed in es6.
This website Uses the example export default 5 * 7; as if it were a legal, static export. This seems reasonable since it clearly evaluates to the static value of 35, but I'm wondering what exactly qualifies as a static export now.
This Code uses export default Backbone.Router.extend({...}); as if it were a legal, static, export. This seems fishy to me as it seems like a dynamic export to me (exporting the result of a function call).
The second example only exports the result of the function call, which is static. The function is only called once, thus the result will always be the same on every import.
An Example to illustrate:
f.js
function f() {
return 2 * Math.random();
}
export default f(); // Is called, before the export is defined. Result: 1.23543
i1.js
import f from 'f';
console.log(f); // 1.23543
i2.js
import f from 'f';
console.log(f); // 1.23543 as well
All exports are static in ES6, that is, their exported name resolves to exactly one variable binding in the exporting module and this can be determined by a single look prior to evaluating of the module code.
A module cannot dynamically add or remove exports through execution of code, the list of exported names is fixed by the declaration.
Whether this variable holds a constant or the result of a function call doesn't matter, neither does whether it holds a primitive value or an object. It doesn't even need to be a constant, the content of the variable may change over time (see an example here).
All imports from import statements are static as well, which means that you can explore the dependency graph without executing any module code.
A dynamic import is done by an explicit call to the module loader. Such loads can depend on the control flow of the module, and may differ from run to run. The code needs to manually handle the asynchrony of the process and potential errors.
You can actually have "dynamic" exports through named exports.
If you do something like this
let awesome = 42;
export { awesome };
you're exporting a binding to the variable and not the value
you can later do this
import { awesome } from './awesome';
awesome = 100;
and any place awesome has been imported will now get the updated value regardless of when awesome was imported
reference: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/es-next-beyond/ch3.md#exporting-api-members
you can also have dynamic imports
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Categories

Resources