I have a file that is similar to this:
const COLORS = {
PRIMARY_COLOR: 'red',
SECONDARY_COLOR: 'green'
};
const APP = {
APP_COLOR: GRAY_DARK,
APP_FONT_SIZE: FONT_SIZE_NORMAL,
APP_FONT_WEIGHT: FONT_WEIGHT_NORMAL,
APP_SEPARATOR_COLOR: GRAY_LIGHT
};
export default {
...COLORS,
...APP
};
The issue is when I'm trying to destructure that object from another file, I get undefined values?
import theme, { PRIMARY_COLOR } from '../../../themes/default';
printing the theme object works fine
but printing PRIMARY_COLOR gets undefined
Any help?
The {} syntax in imports is for "named" imports and is not destructuring.
Just do this:
import theme from '../../../themes/default';
const { PRIMARY_COLOR } = theme;
To understand the difference, you first need to know the way they are exported.
In case of React, the export goes something like this
const Component = ...
...
...
export Component;
This becomes available under React.Component and you can import it like import { Component } from 'react';
The way these look under the microscope is:
default.Component
...
While everything else is just under the default object.
If you do a quick console.log of theme, you'll understand what I mean.
I hope this makes sense.
Let's go a little in depth.
Suppose you have the following bit of code:
const a = {
test: 'hello',
};
const b = {
foo: 'bar',
}
export default a;
Now, let's import that
import * as theme from './test.js'
When we do a console.log( theme ) we get
{ default: { test: 'hello' } }
What does this show? It means that the export object of a file contains a default property which is automatically loaded into memory when we do something like import theme from 'test'. However, if you have more than one export, the compiler gives you the option to pick and choose, but at the same time, provides you with a default object just for fall back.
In your case, you have exported everything under the default. When you do import theme from './theme' all works fine. However, when you do { PRIMARY_COLOR }... it tries to find something which was exported like
export PRIMARY_COLOR...
I hope this makes it clear! :)
Related
I want to have multiple exports from the same file, one of them being a higher order component that is renamed as default, but I'm receiving a syntax error.
//Shape.js
import React, { createContext, memo } from "react";
const ResizeAPI = createContext();
const Shape = (props) => {
/* ... */
}
export {
memo(Shape) as default, // <-- Syntax/Parsing Error: Unexpected token, expected ","
ResizeAPI
};
If I don't wrap the Shape component there is no syntax error:
export {
Shape as default, // <-- This is fine
ResizeAPI
};
Also, if I export only the main component, even if it's wrapped, there is no syntax error:
export default memo(List); // <-- This is fine
How can I export a renamed HOC within a list of exports?
The problem is that you export an object without a valid key, but you also can't have a key with as default syntax, try something like:
// preferable
export default memo(Shape);
export { ResizeAPI };
// or
const MemoShape = memo(Shape);
export { MemoShape as default, ResizeAPI };
I'm working on a project with nuxt.js and I want to implement the atomic design methodology
so I currently import the components like this
import ButtonStyled from '#/components/atoms/ButtonStyled.vue'
import TextLead from '#/components/atoms/TextLead.vue'
import InputSearch from '#/components/atoms/InputSearch.vue'
but I need to import like this
import {
ButtonStyled,
TextLead,
InputSearch
} from '#/components/atoms'
the closer I got was that,
/atoms/index.js
const req = require.context('./', true, /\.vue$/)
const modules = {}
req.keys().forEach(fileName => {
const componentName = fileName.replace(/^.+\/([^/]+)\.vue/, '$1')
modules[componentName] = req(fileName).default
})
export const { ButtonStyled, TextLead } = modules
but I'm still defining the export variable names statically, I need to define dynamics based on the components inside the folder
NOTE: I can not use
export default modules
if I use the above code snippet I will not be able to import the way I need it, which is:
import { ButtonStyled } from "#/components/atoms"
require.context is a quite obscure function in Webpack, you will have issues while running unit tests. But, to solve your problem; You will need to import the index.js file in the main.js of your project.
This is how I do it:
_globals.js
// Globally register all base components prefixed with _base for convenience, because they
// will be used very frequently. Components are registered using the
// PascalCased version of their file name.
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
const requireComponent = require.context('.', true, /_base-[\w-]+\.vue$/)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = upperFirst(
camelCase(fileName.replace(/^\.\/_base/, '').replace(/\.\w+$/, ''))
)
Vue.component(componentName, componentConfig.default || componentConfig)
})
components/index.js
//...
import './_globals'
//...
main.js
//...
import './components' // This imports in the index.js
//...
This way your components loaded in with require.context() gets registered as a vue component and made globally available. I advice to only use global components with components that will be used a lot. Do not load a component globally if you intend to use it only one time.
You can find a working example here -> https://github.com/IlyasDeckers/vuetiful/tree/master/src
To get your unit tests working with jest, you will need to mock require.context(). This was a true pain, but can be achieved easily by using babel-plugin-transform-require-context
I try to use your way to do that, and known you have make a mistake at module.exports
module.exports can not use import , i think you may can do like this
at atoms/index.js
const req = require.context("./", true, /\.vue$/);
const atoms = {};
req.keys().forEach(fileName => {
const componentName = fileName.replace(/^.+\/([^/]+)\.vue/, "$1");
atoms[componentName] = req(fileName).default;
});
export default atoms;
at where to use
import k from "#/components/atoms/index.js";
export default {
components: {
test1: k.test1,
test2: k.test2
}
};
or index.js
import test1 from "./test1.vue";
import test2 from "./test2.vue";
export { test1, test2 };
and where to use like this
import {test1,test2} from "#/components/atoms/index.js";
export default {
components: {
test1,
test2
}
};
I created a library that does all this for me, maybe it helps other people.
named-exports
I have a index.ts file for export libary, but I got error message like below, what's wrong overhere?, I thought it should work.
// components
import List from './components/List'
import Item from './components/Item'
// containers
import ListStackConatiner from './containers/ListStackConatiner'
const components = {
List,
Item
}
const containers = {
ListStackConatiner
}
export {
...components,
...containers
}
SyntaxError: /somepath/src/index.ts: Unexpected token (17:2)(line in ...components)
You can't do destructuring inside a named export natively - this answer explains why. Instead, you can use Object.assign:
export default Object.assign({}, components, containers);
You could also destructure into another variable, then just export that:
var exportObj = {
...components,
...containers
};
export default {exportObj};
Use
export = {
...components,
...containers
}
instead.
I'm using React, and I have something like this in my code:
renderDetails.js:
export default renderDetails = (details) => {
// function logic removed for brevity
}
Then, in the same folder, I have another source file from where I want to import it, and I do something like this:
businessDetails.js:
import renderDetails from './renderDetails';
// rest removed for brevity
But, I get an error message pointing to my renderDetails.js file and says: "rederDetails is not defined". Any ideas what the problem might be and how to fix it?
The problem is that even though you are exporting the component as default you are giving it a name which is not defined
You can either do
export default (details) => {
}
or
const renderDetails = (details) => {
}
export default renderDetails;
One more thing, when you are trying to render components, make sure that their name starts with a Uppercase character.
try that way.
functions.jsx
export function renderDetails(details) => {
// function logic removed for brevity
}
then import like,
import { renderDetails } from './functions';
P.S.
./ is for if both files a re in same namespace/folder.
You can also write them like this:
export const exampleFunctionOne = () => {}
export const exampleFunctionTwo = () => {}
Then import the individual functions you require from said file like this:
import { exampleFunctionOne, exampleFunctionTwo } from './exampleFile';
I like this approach when wanting to combine similar functions into one file such as validators or filters making them easy to import and use across your application.
I'm new to React, but not to JS.
Here's a piece of code, that I couldn't understand
// #flow
import React, { Component } from 'react';
import ShowCard from './ShowCard';
import Header from './Header';
class Search extends Component {
state = {
searchTerm: ''
};
props: {
shows: Array<Show>
};
handleSearchTermChange = (event: SyntheticKeyboardEvent & {target: HTMLInputElement}) => {
this.setState({ searchTerm: event.target.value });
};
render() {
return (
<div className="search"></div>
);
}
}
export default Search;
Within the class there are expressions like state = ... and props: {...
Also function definitions like render(){} and handleSearchTermChange = (....
As I recall from all these valid ES6 one is render. How does it work? If I switch the way data assigned to state/props - everything brakes. I assume it's some kind of babel plugin, is it?
Yes, you're right.
The react docs usually defines state via the constructor() {} object. However, in certain projects, we can simply do so via state = {}. This shorthand syntax is possible due to a Babel transpiler called Class properties transform.