JavaScript export 2 functions - javascript

I'm using React, Redux and now trying to include Material-UI. The Reduct and the Matrial-UI libs are showing example code that has an export at the end.
Redux:
export default connect(mapStateToProps, actions)(myComponent)
Material-UI:
export default withStyles(styles)(myComponent);
When I'm trying to bring both exports together, I have to get rid the default. So I thought it should look like this
This does not work:
export {
connect(mapStateToProps, actions)(myComponent),
withStyles(styles)(myComponent)
}
Error:
"Syntax error: Unexpected token, expected , (120:15)
export {connect(mapStateToProps, actions)(myComponent)}
^
This doesn't work:
I tried to name the function, but then the function wasn't called, for some reasons I don't know.
import * as myConnect from 'react-redux'
...
export const connect = myConnect.connect(mapStateToProps, actions)(View)
I don't know what is happening 'under the hood' so I'm stuck. Any help is appreciated :-)
EDIT
I haven't found a solution yet but I got around the problem. I split the component (myComponent) into an extra file. The design is event better like that, now it distinguishes between pure components and containers.

There is another solution that a lot of people will need at one point to build HOC (Higher order component). I will suggest using Recompose utility (if you are ok to add another package to your project). Here is a link to great article about it on medium.
So if I will be writing your code here is how I will write to build HOC:
import compose from 'recompose/compose';
//...your component code here
export default compose(withStyles(styles),
connect(mapStateToProps, actions))(myComponent);

{
connect(mapStateToProps, actions)(myComponent),
withStyles(styles)(myComponent)
}
This isn't a valid object; you're missing the keys.
{
myConnectedComponent: connect(mapStateToProps, actions)(myComponent),
myStyledComponent: withStyles(styles)(myComponent)
}

Make them named exports:
export const myConnect = connect(mapStateToProps, actions)(myComponent);
export const myStyles = withStyles(styles)(myComponent);
Then use named imports:
import {myConnect} from './yourscript';

Related

Exporting component using i18n's useTranslation and redux's connect HOCs

My App has used Redux for a long time, with the component exports looking like
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
I'm now introducing i18n's translation library and would like to use the HOC that is included with the useTranslation.
I've attempted a few different ways and seen that Redux has a connect piece of functionality that is supposed to combine HOCs if I understand correctly, however I cannot get this to work.
export default connect(useTranslation(), connect(mapStateToProps, mapDispatchToProps))(MyComponent);
When I load the browser I am shown:
Uncaught ReferenceError: process is not defined
Am I missing something here?
useTranslation is not a HOC, you want withTranslation. That will look like this:
export default connect(mapStateToProps, mapDispatchToProps)(withTranslation()(MyComponent));
Or, since the order doesn't matter:
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(MyComponent));
Nesting multiple HOCs can be hard to read, so it may be easier to use a compose utility function. Redux even includes one:
import { compose, connect } from 'redux';
//...
export default compose(
connect(mapStateToProps, mapDispatchToProps),
withTranslation()
)(MyComponent);

Why does named export lead to "Export default was not found"..error

I'm trying to add the React useReducer() hook to an existing Redux project, and after a little bit of refactoring I get a compile error:
export 'default' (imported as 'estateAgent') was not found in './estateAgent'
Other questions about this message, such as
Export default was not found
explain how to declare a default export, but that's not what I need. This is supposed to be a named export, and I don't know why React is expecting a default.
Here are some relevant code snippets.
The line that causes the error is in index.js:
import {EstateAgent} from '../pages/EstateAgent'
(the curly braces mean that it's a named, not a default, export). EstateAgent.jsx contains a container function which defines:
const EstateAgent = (props) => {...
(Going by a web example I'm reading, I changed the original container class EstateAgent to a function)
and the connector:
export const connectEstateAgent = connect(
mapStateToProps,
mapDispatchToProps
)(EstateAgent)
The lowercase "estateAgent" seems to mean a Redux file estateAgent.js which defines actions and a reducer and is imported by EstateAgent.jsx, but doesn't contain any default keyword or any entity actually named estateAgent, so I don't know how the error line came up with that name. e.g.:
export const estateAgentReducer = (state = initialState, action) => {...
So, the question: why is the compiler insisting that I'm trying to import a default export when I don't mean to?
The naming syntax I described is completely correct, but I was looking at the wrong import statement in a different index.js file. The "EstateAgent" name was fine, but estateAgent is the name of a reducer method referenced in the redux subdirectory ./src/redux/index.js . I had renamed this too out of an overabundance of caution and the error was at first masked by a different compile error. When I updated the name in that file, it worked:
import {estateAgentReducer} from './estateAgent'
Takeaway: the error message is pretty accurate, but overlapping file names and reuse of component names with different capitalization can be confusing for those like me who are still learning to navigate React.

JS `import` is undefined, potentially circular import issue?

Preface
I'm using create-react-app to generate an application.
Problem
TodoList === undefined
Code
components/index.js
export { default as App } from './App/App.js';
export { default as TodoList } from './TodoList/TodoList.js';
containers/index.js
export { default as VisibleTodoList } from './VisibleTodoList.js';
components/App/App.js
import { VisibleTodoList } from '../../containers/index.js';
containers/VisibleTodoList.js
import { TodoList } from '../components/index.js';
components/TodoList/TodoList.js
export default function TodoList({ todos, onTodoClick }) { ... }
TodoList is now undefined. I believe it may have something to do with the fact that I have some sort of circular issue.
The thing is, if inside containers/VisibleTodoList.js I import using the following method, everything works fine.
import TodoList from '../components/TodoList/TodoList.js';
What is so special that breaks the import, if I try to import using a 'middleman' (the components/index.js file).
Full code
I have created a CodeSandbox that contains my full code, as it stands in my application. The application is pretty simplistic, but more complicated than I have outlined here.
https://codesandbox.io/s/m54nql1ky9
The problem is caused by the order of exports in your components/index.js file.
export { default as App } from './App/App.js';
export { default as TodoList } from './TodoList/TodoList.js';
Since App.js imports VisibleTodoList which needs to import TodoList and pass it to the redux connect function before it can export itself, you end up with a conflict.
I'm not sure if this is a implementation quirk of babel, or if this is a logical result from how the ES import spec is defined.
In any case, changing the order of exports fixes the bug.
export { default as TodoList } from './TodoList/TodoList.js';
export { default as App } from './App/App.js';
As a rule of thumb, if you can't refactor your files to avoid the import loop, you should put the outer layer component last in the list, since it might rely on imports higher up in the list.
Full working codesandbox here: https://codesandbox.io/s/74mlwnwyy1

How to get around airbnb eslint import/prefer-default-export rule when using index.js for exports

For cases like this,
/ACollectionOfTinyComponent/index.js
import Container from './Container';
export {
Container,
};
So the index.js becomes a directory to include other small parts without having to write each Component Name out all the time.
So in this case, we can import a component in another component like following:
import {Container} from './ACollectionOfTinyComponent'
//then use Container in the code here
Is this a bad practice? Since if I have airbnb linter enable then I got error linting of
Prefer default export import/prefer-default-export
it asks me to add default but that will cause compile error
I found out that because I added only ONE import & export for the index.js. But if I add more than one its fine!
For example, if I do
import Container from './Container';
import Ezeewei from './Ezeewei';
export {
Container,
Ezeewei,
};
Note that I added one more import of Ezeewei.
Then the linting rule will pass!
it asks me to add default but that will cause compile error
You must be using the wrong syntax for exporting a default.
export { name1 as default, … };
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#Syntax
import {Container} ... Is this a bad practice?
Yes. If you have a single entry point into a component (like a a class), you should export it as the default rather than a named export. The designers of the language gave default imports and exports a special syntax to promote it as the primary use case.
http://2ality.com/2014/09/es6-modules-final.html#default-exports-are-favored

You must pass a component to the function returned by connect. Instead received undefined

The code below gives
Uncaught Error: You must pass a component to the function returned by connect. Instead received undefined
List.js
import React from 'react';
import { connect, bindActionCreators } from 'react-redux';
import PostList from '../components/PostList'; // Component I wish to wrap with actions and state
import postList from '../Actions/PostList' //Action Creator defined by me
const mapStateToProps = (state, ownProps) => {
return state.postsList
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({"postsList":postList},dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(PostList);
PostList.js
import React from 'react'
export const PostList = (props) => {
return <div>List</div>
}
Please help me with a solution?
You are doing import PostList from '../components/PostList'; so you need to use export default in your PostList.js file.
Otherwise you need to do import { PostList } from '../components/PostList';.
To whoever is interested, here is a nice article about es6 import/export syntax: http://www.2ality.com/2014/09/es6-modules-final.html
Not related to the asker specifically, but if you're facing this error, it's worth to check if you have the connect() syntax right:
const PreloadConnect = connect(mapStateToProps, {})(Preload);
export default PreloadConnect;
Note that Preload, is passed as a IIFE parameter.
More details can be found here.
There might be three reasons, that are summarized as follows:
Circular dependencies between components
Wrong usage of export and export default then imported the wrong way
Used the connect function wrongly, passed the wrong parameters
In my case is was Circular dependencies, and the circular-dependency-plugin helped me fix it.
In my case it was Expo server that sometimes doesn't catch filesaves on Windows (probably) and it was seening old version of the component I've tried to connect (I had no export there yet probably). Re-saving my component without really touching anything fixed the issue.
Restarting Expo server with cleaned cache would probably help as well.
In my case, it was because of the usage of enums (TypeScript).
Try without enums in your code.
Reason : Enums can go undefined during runtime.
Link to Related Question
Hope it solves your problem :)

Categories

Resources