ES6 Destructuring and Module imports - javascript

I was under the impression that this syntax:
import Router from 'react-router';
var {Link} = Router;
has the same final result as this:
import {Link} from 'react-router';
Can someone explain what the difference is?
(I originally thought it was a React Router Bug.)

import {Link} from 'react-router';
imports a named export from react-router, i.e. something like
export const Link = 42;
import Router from 'react-router';
const {Link} = Router;
pulls out the property Link from the default export, assuming it is an object, e.g.
export default {
Link: 42
};
(the default export is actually nothing but a standardized named export with the name "default").
See also export on MDN.
Complete example:
// react-router.js
export const Link = 42;
export default {
Link: 21,
};
// something.js
import {Link} from './react-router';
import Router from './react-router';
const {Link: Link2} = Router;
console.log(Link); // 42
console.log(Link2); // 21
With Babel 5 and below I believe they have been interchangeable because of the way ES6 modules have been transpiled to CommonJS. But those are two different constructs as far as the language goes.

To do this:
import {purple, grey} from 'themeColors';
Without repeating export const for each symbol, just do:
export const
purple = '#BADA55',
grey = '#l0l',
gray = grey,
default = 'this line actually causes an error';

Except for different exports, it may also lead to
different bundled code by WebPack when using two variant ways to destruct ESM modules:
// react-router
export function Link(str) { /* ... */ }
Destruct within the import statement:
import {Link} from 'react-router';
Link('1');
Link('2');
// WebPack output
var util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1);
(0,util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__.Link)('1');
(0,util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__.Link)('2');
Use destructuring syntax:
import * as Router from 'react-router';
const {Link} = Router;
Link('1');
Link('2');
// WebPack output:
var util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1);
const {Link} = util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__;
Link(1);
Link(2);
As you can see in the output example above where there is redundant code, which is not good for optimization when trying to uglify via UglifyJS, or Terser.

Related

Can't import jwt-decode in JavaScript file in React project

I created a React app and I try to make a separate file for functions.
I required 'jwt-decode' library like that:
const jwt_decode = require("jwt-decode");
After that I used it like that:
const verifyToken = (token) => { console.log(jwt_decode(token)); };
And exported like that:
module.exports = { verifyToken };
When I tried to use it in my react page, I saw this error in the console:
Uncaught TypeError: jwt_decode is not a function
What I did wrong?
You need to require the default export:
const { default: jwt_decode } = require("jwt-decode");
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
console.log(jwt_decode(token));
Expected output:
{ sub: '1234567890', name: 'John Doe', iat: 1516239022 }
Alternatively use import when type in package.json is set to module.
import jwt_decode from "jwt-decode";
It looks like you are trying to use CommonJS require syntax in a React app that is likely using ES6 import syntax.
Try changing your code to the following:
import jwt_decode from "jwt-decode";
const verifyToken = (token) => { console.log(jwt_decode(token)); };
export default { verifyToken };
And then in your React page, use:
import verifyToken from './path/to/your/file';
It works to me!

How can i export an import for its side effects only in ecmascript 6?

Recently i saw a video that i guy was exporting a module in commonjs:
// src/routes/index.js file
module.exports = [
require('./user'),
require('./auth'),
require('./demo')
]
// src/routes/user.js
const exppres = require('express')
const api = express.Router()
api.post('/user' , doSomething())
// src/handler.js
const express = require('express')
const api = require('./routes')
const app = express()
app.use(api) // add all routes
I tried all different ways of doing, like:
export default {
import "./user",
import "./auth"
}
and in server layer
import api from './routes'
but nothing works...
Someone knows how to do it?
Try this
module.exports = {
user:require('./user'),
auth:require('./auth'),
demo: require('./demo')
}
Then access them like this
const {user,auth, demo} = require("path to the expoted module")
I don't quite understand what you mean by "for its side effects only", because then you wouldn't need to export anything. Importing for side effects only is done like this with ES6 modules:
import './user';
import './auth';
import './demo';
If you wanted to re-export something from these modules, you'd typically write
export * from './user';
export * from './auth';
export * from './demo';
or
export { default as user } from './user';
export { default as auth } from './auth';
export { default as demo } from './demo';
You would not export an array.

"Element type is invalid: expected a string" in the definition of my main component: export const Autocomplete = (props) => {....}

I am new in react.
My main component is defined in the way:
import React from "react";
import { useState } from "react";
export const Autocomplete = (props) => {
return (
<div className="wrapper">
hello
</div>
);
};
I am getting this error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
this is my index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<App /> <!--my main component-->
</StrictMode>,
rootElement
);
what am I doing wrong? thanks
Answer
You've made your main component a named export named Autocomplete, but you are importing a default component called App.
Try this:
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { Autocomplete } from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<Autocomplete /> <!--my main component-->
</StrictMode>,
rootElement
);
Explaining Named vs Default Exports
There are two ways of exporting and each way requires you to import the exported member differently.
Named Export/Import
Named exports have to be imported using the same name as the exported member. The import will also have braces around the imported members. You can export multiple members from a single file.
foobar.js
export const foo = 'foo';
export const bar = 'bar';
const baz = 'baz';
// or
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
export {foo, bar};
main.js
import { foo, bar } from './foobar'
Default Export/Import
Default exports can be imported using any name you want. There will be no braces around the import. You can only default export a single member from a file.
foobar.js
export default {foo: '', bar: ''}; // directly exporting the value (an object), no variable declaration involved
// or
const foobar = {foo: '', bar: ''};
export default foobar;
main.js
import foobar from './foobar';
const foo = foobar.foo;
const bar = foobar.bar;
// or
import whatever from './foobar';
const foo = whatever.foo;
const bar = whatever.bar;
Named and Default Export/Import
You can also have both default and named exports from the same file. You may have seen this with React.
foobar.js
export const foo = 'foo';
export const bar = 'bar';
export default foobar = 'foobar';
main.js
import myFoobar, { foo, bar } from './foobar'
import React, { useState } from 'react';

Why can't I `import {}` from `export default {}` in typescript

I have a typescript file:
#util.ts
export default {name: 'name'}
I import it from another file:
import {name} from './util'
It fails to compile with the error util has no exported member name. How should I import it in typescript?
Your util.ts file exports a default export, while you are requesting a named export. You must change your import to request the default export:
import name from './util';
See the difference in this article.
If you want to access the value of the name field consider using a named export in your util.ts:
export const name = 'name';
or:
const name = 'name';
export {
name,
}
and then import with:
import { name } from '/util';

Barrel in Vuejs

It's possible to do a barrel in Vuejs?
If yes, please show a example, I search in the web, but i didn't find anything
Like js
// app/domain/index.js
export * from './negotiation';
export * from './negotiations';
// app/app.js
import { Negotiation, Negotiations } from './domain';
You can do
export {default as MyModule} from './MyModule.vue';
When I barrel .vue files I do it this way:
Creating the barrel
//index.js
import File1 from './file1'
import File1 from './file1'
export {
File1,
File2
}
Using the barrel file
import { File1, File2 } from './path'
Probably, this will work:
// app/domain/index.js
import NegotiationModule from './negotiation';
import NegotiationsModule from './negotiations';
export const Negotiation = NegotiationModule;
export const Negotiations = NegotiationsModule;
// app/app.js
import { Negotiation, Negotiations } from './domain';
(I haven't tested it, so it could not work)
Create index.js file in the same folder as the components (negotiation, negotiations)
app/domain/index.js
import negotiation from './negotiation.vue'
import negotiations from './negotiations.vue'
export default { negotiation, negotiations };
app/app.js
import domains from './domain';
const { negotiation, negotiations } = domains;
export default {
components: { negotiation, negotiations }
}

Categories

Resources