I have two module with the exact same name that belongs to two different apps, these two module are functionally quite similar except for the styling. I am creating a master component and try to import these two different module based on what app I am currently in.
I wonder if there is a way to conditionally import the module that I don't have to hard code a name space for the module, like module_app1 and module_app2 but instead to do
if (cond) {
import module from 'path1';
} else {
import module from 'path2';
}
I use 'as'. Example:
import Actions from '../actions';
import { Actions as Navigator } from 'react-native-router-flux';
Related
In React when you wanna import components from other files we use:
import ComponentName from 'somePlace';
That works fine, but I wanna know if there is a way to import the content of a file instead of the exports. I wanna put all import statements for components in a single file (e.g. imports.js) and have a statement like:
import './import.js' to all documents;
so all my components are automatically imported everywhere.
Is there a way to do that?
Globally import modules? Not really, no. And neither should you need to.
A hacky "solution" would be assigning all imports to the global context (e.g. window in the browser) so it's accessible that way. That's possible, but definitely not recommended. It'll also prevent your bundler (most likely Webpack) from optimizing a lot of code.
Apart from the technical aspect, there are other reasons not to do so. If you specify the imports in each file, you know exactly what imports that file needs and under what variables it is imported as for that file.
If you still want to simplify importing the same components over and over again, you can have this setup:
imports.js
// For default exports
import ComponentA from 'wherever';
export { ComponentA };
// For regular exports
//import { ComponentB } from 'wherever';
export { ComponentB } from 'wherever';
// For whole modules
//import * as wherever from 'wherever';
export * as wherever from 'wherever';
someOtherFile.js
// Either import as a namespace
import * as Imports from './imports';
console.log([
Imports.ComponentA,
Imports.ComponentB,
Imports.wherever.someFieldFromTheWhereverModule,
]);
// Or partial import
import { ComponentA, ComponentB } from './imports';
I have a files like this:
components/carousel.js
import hammerjs from 'hammerjs';
import React from 'react';
export default () => <div>...</div>;
components/layout.js
import React from 'react';
export default () => <div>...</div>;
components/index.js
export { default as Carousel } from './carousel';
export { default as Layout } from './layout';
Now in my server side rendered app I import layout like so:
import { Layout } from './components';
I get an error about window not being defined, because it's reading through components/index.js and seeing hammerjs dependency inside the Carousel export, which requires window and isn't available on the server.
Why is it reading the code in the Carousel component when I'm only trying to import the Layout component? How do I avoid this happening?
In short - why is it reading the Carousel component?
You are exporting two defaults in your components/index.js which is not a supported operation. Export the named components individually or one default objet that holds both.
1) From MDN on import/exports - You can have multiple named exports per module but only one default export. link
In your components index file you're exporting both as default - export the named variable. Then import the named variable.
2) The HammerJS dependency shouldn't matter. Your react code will be run through some sort of transpiler that will take the node modules and turn them into something the browser can understand.
I was browsing through this repo on Github and was trying to comprehend the working of the code
Here, the author (or programmer) have mentioned import * at multiple places so I am trying to comprehend and understand how import * work?
First in Game.js file of his repo he have mentioned/written like this
import * as actions from '../actions';
In VS Code, when if I click on '../actions using command It is redirecting me to this file -> index.js
then in Index.js they have something like this
import * as ActionTypes from './action-types';
when I click on ./action-types it redirects me to here action-types.js
I went through firefox docs but I wasn't able to clearly make sense for the first example like for one, the action folder contains multiple files and how does import * as actions from '../actions'; mean index.js file
While i get he have called/referenced the functions using actions.functionName() or ActionType.TypeName
My Prime question remains
how does import * as actions from '../actions'; mean index.js file ?
The import * as name syntax imports all exported content of a javascript file.
For example, if you want to import an entire module's contents, then access the doAllTheAmazingThings() function
import * as myModule from '/modules/my-module.js';
myModule.doAllTheAmazingThings();
From the docs
Import in js is new syntax of ES6 to import a module it has the same work of require but its easier to filter what do you want in a module
In your example you import * as actions from '../actions'; you import all function from ../actions file
its same to do const actions = require('../actions')
but its easier to manage what you want
this syntax is not work on all browser so be sure to use transpiler with babel or other
you can see this syntax in python too
When you reference a directory in an import statement, it looks and loads the index.js file in that directory. What I usually do there is export classes and functions under that directory in a grouped object, so they can be easily accessed:
For instance in index.js I export sth like:
{
Class1,
method1
}
where each is imported as such:
import Class1 from './Class1';
So they just group the classes/methods/... that are in files in the directory.
Then you can easily access it as such:
import { Class1, method1 } from './mymodule';
vs
import Class1 from './mymodule/Class1';
My broader question is does an import of a module get shared between two components and why?
First what do I know about import. You can import in two different ways.
1.
At the top of your file which loads the imported module into a variable which you then can use.
import Highcharts from './highcharts'
// create a chart
Highcharts.Chart()
2.
Or dynamically anywhere in your code which returns a promise:
import('./highcharts').then((response) => {
// create chart
response.Chart();
});
But there is this weird behavior I don't understand when using import with react. If I have the following component:
import React, {Component} from 'react';
import Highcharts from 'highcharts/js/highcharts';
export default class Chart extends Component {
state = {
chartOptions: {
// my chart options and data
}
}
componentDidMount() {
if(this.props.extendFunc) {
import('highcharts/js/modules/funnel.src.js').then((funnelModule) => {
funnelModule(Highcharts)
})
}
Highchart.Chart('myChart', this.state.chartOptions)
}
render() {
<div id="myChart" />
}
}
I use the component from above twice. Now there is this behavior that both components use the same import e.g. the import of Highcharts does not happen twice. I noticed this because with Highcharts there is the option of extending the functionality.
If I for example extend the functionality for Chart 1 by passing a prop to extend it, the functionality of Highcharts is also extended in Chart 2, although I didn't pass a prop to extend the functionality.
import React, {Component} from 'react';
import Chart from './Chart';
export default class Dashboard extends Component {
render() {
return (
<div>
<Chart extendFunc={true}> Chart 1 </Chart>
<Chart> Chart 2 </Chart>
</div>
)
}
}
What causes this behavior? Is this react or is this just the way import works? Are imports global for multiple instances of the same component? Or are imports of a node module the same for the whole application?
What causes this behavior? Is this react or is this just the way import works? Are imports global for multiple instances of the same component? Or are imports of a node module the same for the whole application?
This is the way imports work. When you import something for the first time, the file is run and the exported values from it are returned back to the one importing it. When something is imported again, those same exports are reused and returned. Node JS modules work the same way.
Sometimes this behavior is helpful, firstly for performance to avoid unnecessarily re-running the same file over again, and also if the module wants to store some internal state. For example, counting the number of times a function is called from anywhere in the application.
In cases like this, where you need a single instance of something for each script, modules will usually give you a way to actually make an instance of that thing. For example, I might have a logging module, which exports a Logger class, then I can make new instances of that class for each component, and configure each logger separately.
For your case, look in the docs to see if there's a way to make per-component instances of Highcharts and extend that individual instance with the functionality you need.
When you extend <Chart /> with a prop extendFunc it will be extended in your Chart Component and not in your "new" Component.
That means, if you call the component, it will always have the props you gave it, but you will not have to use them (if there are not set as required).
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Observable } from '#rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/observable/throw';
#Component({});
export shellModule{}
This is a piece of code form my Angular app that I copied from somewhere (I have removed the definitions in the exported module. I am using it to make a service to call APIs.
In the imports in this particular file, why is it that Observable is imported separately even though the entire rxjshas been imported. If a particular module is being imported in its entirety, why is a particular object from it imported separately? I tried asking this question at the forum from where I took it, but there was no answer. I want to understand if this somehow helps with optimization of code.
In general:
In Typescript, the way modules are handled would require you to either load in the entire library with the import * as rx from 'rxjs/Rx', or a specific exported module within the library to use it, so the the compiler loads in the types.
Reducing your imports to only the specific modules you need sets up your app to use tree shaking from Angular's AOT compilation. This is not done by the typescript compiler, but by a tool called rollup. So, it can help with optimizing code later, but it doesn't automatically do so.
As far as compilation overhead, bringing in the whole library might slow down the compiler a bit... but this isn't a very strong point except for massively complex libraries.
I, personally, prefer importing in specific modules because it makes the calling code a little cleaner since I don't need to use that global name to get to the specific name. rx.Observable vs Observable. A good example of this is the lodash library (rxjs is a bit more complex...)
Honestly, importing entire libraries like the line you have there: import 'rxjs/Rx' doesn't make sense to me. You should only import specific exported modules. Try removing it, seeing what errors you get, and then using the * as rx syntax instead.
As far as rxjs goes - it is a little wonky when you want to import specific operators like this question does - so the way to get specific operators is with: import 'rxjs/add/observable/from' - but that also requires a tinkering with your webpack set up as outlined in the referenced question's answer.
Let's see what the rxjs/Rx module exports:
export { Subject, AnonymousSubject } from './Subject';
export { Observable } from './Observable';
export { Operator } from './Operator';
export { Observer } from './Observer';
export { Subscription } from './Subscription';
export { Subscriber } from './Subscriber';
export { AsyncSubject } from './AsyncSubject';
export { ReplaySubject } from './ReplaySubject';
export { BehaviorSubject } from './BehaviorSubject';
...
import './add/observable/bindCallback';
import './add/observable/bindNodeCallback';
import './add/observable/combineLatest';
...
So it exports RxJs classes and also imports operators from the add folder. So as you can see it loads everything in the library. It doesn't export any global object though. So you need to use named export like this:
import * as Rx from 'rxjs/Rx'
to be able to use an exported class:
Rx.Observable.of(12, 3);
This emulates what you would have if you loaded the library using the bundle - a global Rx object:
<script src="rxjs/bundles/Rx.js">
If you want to use Observable without Rx global object, you need to import it separately:
import { Observable } from '#rxjs/Observable';
Observable.of(1);
Importing both
import { Observable } from '#rxjs/Observable';
import 'rxjs/Rx';
is not a good practice, but may be used if you don't want to import every operator separately.
Also see How to correctly import operators from the rxjs package.