Are variables defined outside of a react component considered global? - javascript

I know that using global variables are a bad practice. I also know in javascript variables defined outside of a function are considered global. Is this also true for variables defined outside of a react component, be it a functional component or a class. It appears as no because some css in js libraries use syntax like this but I don't understand why it wouldn't be a global. For example:
import ...
const styles = ...
const MyComponent = () => {
...
}
export default MyComponent
Is styles a global variable here? Why or why not?

In React, as in many modern Javascript frameworks, they use script modules, which sandbox each script. This means that you cannot define a global unless you specifically assign something to the window object.
const local = {};
window.global = {};
A script module is defined by setting a script tag's type to be module:
<script type="module" src="myscript.js"></script>
You should see the resulting HTML that react creates contains these script types.

Related

sveltejs - static properties on components

I have a scenario where I need to provide information to a component class such that downstream instantiations can make use of that info.
For instance:
import { AComponent } from 'AComponent.svelte'
...
AComponent.classInfo = {something: somedata}
And then, the component could access that information as in:
<script>
let something = AComponent.classInfo.something
</script>
There seemed to be some effort in providing this kind of functionality in V2 (I'm using 3) that was discussed in these issues: Support Component Static Method #480, which resulted in Added setup function which can supply static methods/properties. #572.
However, scanning the current docs reveals no such setup method. So, did this survive from V2 to 3 & if not, is there some way to do this?
You can define static properties that are not instance specific in the module script block
<script context="module">
export const someValue = 123
</script>
<script>
// Normal component stuff
</script>
and then import it directly from the component file:
import { someValue } from './MyComponent.svelte'
Note that this is a value shared among all instances of this component.
At least in version v3.32, it's not possible to define static properties in a Svelte Component. Only named exports are possible.
The only workaround I known is using a custom webpack loader/rollup plugin, and the implementation is never pretty.

Exporting a module object and importing specific properties of said module

I'm writing a JS Module, in which I want to export an object concerning functions declared in the same file.
Ideally, I would like to import only the properties of the exported object, instead of importing the whole object and deconstructing it. Is it possible in some manner?
module.js
export const foo = {
bar: () => console.log("foobar")
}
component.js
import { bar } from './module.js'
bar();
The current problem is that the bar isn't recognized as a function.
I'm writing a JS Module, in which I want to export an object with reference to functions declared on the same file.
There's no reason to have that object. That's what modules are for. The bindings you export become part of a module object (you never get a direct reference to it), so there's no need for you to explicitly create the object — and doing so gets in a the way a bit, and prevents tree-shaking (eliminating code that is never used).
Ideally, I would like to import only properties of the exported object, instead of importing the whole object and deconstructing it.
With your current approach, that's what you have to do, e.g.:
import { foo } from "./module.js";
then to use bar, either use foo.bar(); or destructure:
const { bar } = foo;
bar();
That's because what you've exported isn't bar, it's foo, an object that has a property called bar. Your import should be failing, because there's no named export called foo. (But if you're using a bundler, it may be obscuring that error.)
But again, there's no need for that object. Instead, just do this:
module.js:
export function bar() {
console.log("foobar");
}
or
export const bar = () => {
console.log("foobar");
};
Then your import in component.js will work.

Call react component function from javascript

I have one question because I'm not sure if that possible. I have ReactJS project that included some javascript functions.
I found solution to call javascript function from react components with window object but is it possible to call function from reactcomponents in javascript script?
For example I have definied function in React component. Is it possible to call that function in javascript?
Thank you.
A function that is supposed to be used outside React application bundle should be exposed to global scope:
window.foo = () => { /* ... */ };
Then it can be accessed as such:
<script src="react-app-bundle.js"></script>
<script>
foo();
</script>
In case React application bundle is published as UMD module, it can export a function in entry point:
export const foo = () => { /* ... */ };
its namespace will be exposed to global scope when it's loaded via <script>:
<script src="react-app-bundle.js"></script>
<script>
ReactAppNamespace.foo();
</script>
This is the case for a lot of third-party React libraries, React itself exposes React global.
It's preferable to put all code that depends on React application internals to the application itself, so accessing globals is not needed.

How to access the context of imported modules in ES6?

I might have my terminology mixed up, but in the same manner that I can access the global context through window, I would like to access the current context of my imported modules.
To give a simple example of what I'm doing, imagine we have a file called MyClasses.js which contains the following two classes:
export class MyClass1 {}
export class MyClass2 {}
Then we import said classes into a file called main.js
import {MyClass1, MyClass2} from './MyClasses'
In main.js I might construct a new instance of each class based on some property value.
function main()
{
const config = { case1: 'MyClass1', case2: 'MyClass2', case3: 'MyClass1' };
const myPropValue = 'case3';
const constructorName = config[myPropValue];
const myClass = new context[constructorName](); // MyClass1
}
This is a basic example, but in a situation where there are many classes and cases for constructing such classes, I'd like to map the relationship rather than depend on intricate if/else logic.
One solution would be to attach the imported classes to the window context...
window.MyClass1 = MyClass1;
window.MyClass2 = MyClass2;
... and construct instances of my classes from there:
const myClass = new window[constructorName](); // valid construction
But I'd like to avoid binding these to the global scope. Is there a default context for any imported modules, or do I need to set up a context myself?
Just modify your import and you will be ok:
import * as MyClasses from './MyClasses';

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