I just tried to use a simple HOC with react. Here is the function :
import React from "react"
const withOptions = (WrappedComponent) => {
return class extends React.Component {
render() {
return <WrappedComponent { ...this.props } />
}
}
}
export default withOptions
The problem seems to be in the way i export/import it.
Imported and used in a simple way, it works :
import withOptions from "./Options"
...
class BilanClimatique extends React.Component{
...
}
const StyledBilanClimatique = withStyles(styles)(BilanClimatique)
export default withOptions(StyledBilanClimatique)
But if i use an intermediate file like index.js
import withOptions from "./Options"
export {
withOptions
}
And import it in my ponent like that
import {
withOptions
} from "./index"
Here is what i get
Can someone help me understand this ?
EDIT :
I found that the ponent that is using the HOC is imported from the same file as the HOC :
import withOptions from "./Options"
import BilanClimatique from "./BilanClimatique"
export {
withOptions,
BilanClimatique
}
And that causes the problem, but I don't understand why... Here is a sandbox with the problem
I just tried to use a simple HOC with react. Here is the function :
import React from "react"
const withOptions = (WrappedComponent) => {
return class extends React.Component {
render() {
return <WrappedComponent { ...this.props } />
}
}
}
export default withOptions
The problem seems to be in the way i export/import it.
Imported and used in a simple way, it works :
import withOptions from "./Options"
...
class BilanClimatique extends React.Component{
...
}
const StyledBilanClimatique = withStyles(styles)(BilanClimatique)
export default withOptions(StyledBilanClimatique)
But if i use an intermediate file like index.js
import withOptions from "./Options"
export {
withOptions
}
And import it in my ponent like that
import {
withOptions
} from "./index"
Here is what i get
Can someone help me understand this ?
EDIT :
I found that the ponent that is using the HOC is imported from the same file as the HOC :
import withOptions from "./Options"
import BilanClimatique from "./BilanClimatique"
export {
withOptions,
BilanClimatique
}
And that causes the problem, but I don't understand why... Here is a sandbox with the problem https://codesandbox.io/s/r074735yvo
Share Improve this question edited Aug 1, 2018 at 9:47 Jayffe asked Aug 1, 2018 at 6:03 JayffeJayffe 1,27910 silver badges13 bronze badges 4- I can't seem to replicate it. codesandbox.io/s/wq7xnmmx5w Could there be something else missing when you trimmed your code for SO? – dubes Commented Aug 1, 2018 at 9:05
-
I found the problem and kind of replicate the error: the ponent which is using
withOptions
hoc is also imported fromindex
codesandbox.io/s/r074735yvo ... But i don't understand why this is a problem... – Jayffe Commented Aug 1, 2018 at 9:44 - Thanks for replicating it. I will dig a bit. – dubes Commented Aug 1, 2018 at 9:52
- Thanks for the question, I learnt a lot about modules while digging around. Hope my answer is clear, else let me know and I will try to elaborate further. – dubes Commented Aug 1, 2018 at 11:12
2 Answers
Reset to default 12This seems to be a problem with hoisting of 'exports'. From what I can see, the imports
get hoisted, but I could not see anything similar for exports
.
The flow which causes problem (codesandbox):
App.js:
import { BilanClimatique } from "./ponents/index";
./ponents/index.js:
// just using the "re-export" shortcut
export { default as BilanClimatique } from "./BilanClimatique";
export { default as withOptions } from "./Options";
./ponents/BilanClimatique.js:
import { withOptions } from "./index";
./ponents/Options.js:
const withOptions = WrappedComponent => {
return ... //snipped code
export default withOptions;
When App.js asks index.js for BilanClimatique, it in turn asks the same index.js for withOptions
. But since exports don't seem to be hoisted, index.js has not yet made withOptions available.
How to solve:
- Ordered exports:
in ./ponents/index.js, change the order of exports as per your dependency:
// just using the "re-export" shortcut
export { default as withOptions } from "./Options";
export { default as BilanClimatique } from "./BilanClimatique";
I would not remend it. It is very fragile.
- Use index.js to only expose to outside your namespace. Inside your namespace, rely on explicit imports.
i.e. in ./ponents/BilanClimatique.js:
import withOptions from "./Options";
- If you have a very large codebase, use multiple index.js for exporting your "contracts". Take a look at the codebases of various library authors, I think that is the strategy they take.
I would personally remend #2 over #3 unless you run into problems with #2.
.
doesn't look as a great import path. Try to import from 'index' file.
import {
Logo,
withOptions
} from "./index"