I was experiencing a similar problem. I finally resolved it by following this article: https://medium.com/@ktruong008/absolute-imports-with-create-react-app-4338fbca7e3d
- Create a .env file in the root of the react app
- Add a line
NODE_PATH = src/
That worked for me.
Answer from DigiBanks99 on Stack OverflowI was experiencing a similar problem. I finally resolved it by following this article: https://medium.com/@ktruong008/absolute-imports-with-create-react-app-4338fbca7e3d
- Create a .env file in the root of the react app
- Add a line
NODE_PATH = src/
That worked for me.
It depends on your module bundler. For Webpack 2 you can do something like this:
module.exports = {
...
resolve: {
modules: [
'node_modules',
path.resolve(__dirname + '/src')
],
alias: {
src: path.resolve(__dirname + '/src')
}
},
...
}
the same for Webpack 1:
module.exports = {
...
resolve: {
root: [
path.resolve(__dirname + '/src')
],
alias: {
src: path.resolve(__dirname + '/src')
}
},
...
}
Than you will be able to use src as a native path like this:
import approxPerDay from 'src/utils/approxPerDay.js'
import otherstuff from '../components/otherstuff'
Dynamic import with variable path
reactjs - How to import a component or file in React using variables? - Stack Overflow
Reactjs: How to import an image from a variable path
reactjs - React - inserting variable into Route path - Stack Overflow
Videos
Thereโs limitation when using dynamic imports with variable parts.
Webpack Docs
It is not possible to use a fully dynamic import statement, such as import(foo). Because foo could potentially be any path to any file in your system or project.
The import() must contain at least some information about where the module is located. Bundling can be limited to a specific directory or set of files so that when you are using a dynamic expression - every module that could potentially be requested on an import() call is included.For example, import(
./locale/${language}.json) will cause every .json file in the ./locale directory to be bundled into the new chunk. At run time, when the variable language has been computed, any file like english.json or german.json will be available for consumption.
In your case, during build time for dynamic import in FirstComponent component, bundling was limited to directory where the FirstComponent component was i.e. Components directory.
What it means is that, webpack will find all the files that are in the Components directory and then create chunks for them. Then at runtime when dynamic import is called, webpack will serve the chunk that corresponds to the value passed in.
Since you passed path= '../FooterComp/Footer' has no corresponding chunk so webpack will throw the error.
This is also same for Dynamic component. If you try to dynamically import with variable parts for the files that are outside src folder, you will get same error.
So to solve this you have couple of options
- place both files in same folder
i.e
'src/Components/FirstComponent.js'
'src/Components/Footer.js'
And use
// In FirstComponent.js
componentDidMount() {
const { path } = this.props;
import(`${path}`)
.then(module => this.setState({ module: module.default }))
}
{Component && <Component path='./Footer' />} // Index.js
- be more specific as possible
i.e
// In FirstComponent.js
componentDidMount() {
const { path } = this.props;
import(`../FooterComp/${path}`)
.then(module => this.setState({ module: module.default }))
}
And use
{Component && <Component path='Footer' />} // In index.js
If FooterComp is under src, the path should be './FooterComp/Footer' not '../FooterComp/Footer'
Edit
Index.js
render() {
console.log('in render')
// alert("in render")
const { module: Component } = this.state;
return(
<div>
{Component && <Component path='./Components/FirstComponent' />}
</div>
)
}
}
ReactDOM.render(<Dynamic />, document.getElementById('root'));
FirstComponent.js
render() {
const { module: Component } = this.state;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
{Component && <Component path= '../FooterComp/Footer' />}
</div>
);
}
I'm looking for a way to dynamically import a component from a path including a variable, and display a fallback component. Currently I'm doing this with an intermediary component:
const DynamicComponent = ({ element, elementName }) => {
const [component, setComponent] = useState(element)
useEffect(() => {
import(`/components/${element.type.name}`)
.then(module => {
setComponent(module.default)
})
.catch(console.log)
}, [element])
return component
}Which is then used like this:
<DynamicComponent element={<SomeComponent />} elementName="SomeComponent" />
The elementName prop is required because in production the function names are minified so I can't get the component name from anywhere else.
This seems to work well locally, but is pretty flaky in production - it errors far more often, and sometimes doesn't show the right component which appears to be related to how and when the dynamic path is generated.
Can anyone recommend a cleaner/better/simpler solution?
Thanks!
Unfortunately, you cannot import/require components dynamically in React environment.
Depending on how many buildings/blueprints there are, it's possible to import them one by one, create component-building map and pick component by building ID.
If there are many/infinite components to load, I would surely pick another method - don't know content of your problem.
import BlueprintA from './BlueprintA'
import BlueprintB from './BlueprintB'
import BlueprintC from './BlueprintC'
// ...
class BuildingMap extends React.Component {
render(){
const C = {
buildingA: BlueprintA,
buildingB: BlueprintB,
buildingC: BlueprintC,
// ...
}[this.props.building]
return (
<div className="blueprint" id={this.props.building}>
<C />
</div>
)
}
}
This question is pretty old but as I was looking for how to solve the same problem let me give my answer. It can be done with dynamic import React.lazy:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
See more details here: https://reactjs.org/docs/code-splitting.html#reactlazy
You could have a file import all the images like
//images/index.js
import image1 from './image1.png'
import image2 from './image2.png'
.
.
export default {
image1,
image2,
.
.
}
you can access images dynamically from the object exported from here
import images from './images/index.js'
images['image1']
// or dynamically
let name = 'image2'
images[name]
You can try with:
Using import for browser and nodejs
const picture = (await import(`../path/to/file/${this.props.picPath}`)); // this is async
Using require for browser and nodejs
const picture = require(`../path/to/file/${this.props.picPath}`); // this is sync
Using readFileSync from fs only for nodejs
const fs = require('fs')
// or: import fs from 'fs'
const file = fs.readFileSync(`../path/to/file/${this.props.picPath}`).toString()
Using readFile from fs only for nodejs
const fs = require('fs')
// or: import fs from 'fs'
const file = (await fs.readFile(`../path/to/file/${this.props.picPath}`)).toString()
Tip #1:
When you using require, it only can handle json and js files, but when you using import, it can handle svg, and other stuff. But you can apply some trick like:
// in tsconfig.json
"include": [
"./declarations.d.ts",
],
// in declaration.d.ts
declare module '*.png';
Tip #2:
When you wanna import images like png, you should be define how it work with this:
declare module "*.png" {
const value: any;
export default value;
}
Tip #3
In javascript you can use Template Literals using `` and ${}.
const name = "John"
console.log(`Hello ${name}`);
Create a file called .env in the project root and write there:
NODE_PATH=src
Then restart the development server. You should be able to import anything inside src without relative paths.
Note I would not recommend calling your folder src/redux because now it is confusing whether redux import refers to your app or the library. Instead you can call your folder src/app and import things from app/....
We intentionally don't support custom syntax like @redux because it's not compatible with Node resolution algorithm.
The approach in the accepted answer has now been superseded. Create React App now has a different way to set absolute paths as documented here.
To summarise, you can configure your application to support importing modules using absolute paths by doing the following:
Create/Edit your jsconfig.json/tsconfig.json in the root of your project with the following:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
Once you have done this you can then import by specifying subdirectories of "src" (in the following example, components is a subdirectory of src) e.g.
import Button from 'components/Button'
Maybe try this new ES6 syntax:
const PATH = 'myComponents/ComponentA';
Promise.all(
[
import(`${PATH}`), // try pass it like this
// other imports
]
).then(....);
You have at least to have an initial literal folder string (no variable) to restrict what modules can be loaded, because it will bundle all possible files.
This is a limit of webpack. For details see https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import
It is truly a pity it doesn't recognize the const other than literals.
What's the general consensus on relative import paths? Are people using relative paths to import their components or are you using a different approach? I've detailed the solutions to relative import paths that I'm aware of and why I don't like any of these approaches.
For clarity, below is an example of what I'm referencing
import MyComponent from "../../../components/MyComponent"
Update that to this
import MyComponent from "@components/MyComponent"
Potential solutions and their drawbacks:
-
Relative Import Paths - these are just annoying, there should be a cleaner solution
-
Craco - doesn't work with react-scripts 5.0
-
Utilizing Absolute Import Paths: doesn't directly solve the problem (still need to list all folders below the "src" folder)
-
Webpack from Scratch: Don't use CRA and create webpack config files from scratch: this is a lot of work for simply having aliased imports
Cheers!
There is a new api in react-router-dom 5.1
https://github.com/ReactTraining/react-router/releases/tag/v5.1.0
import {useParams} from "react-router-dom";
function MyComponent(){
const {date} = useParams()
}
In your initial component, set the path that loads your route. By adding /:date to the end of your route, that string can be accessed by calling props.match.params.date inside that routes component.
<Route exact path="/meeting/:date" component={DateComponent} />
In the component that the route renders, use props.match.params.date to access your string from path
Class DateComponent extends React.Component{
render(){
return(
<h2>{this.props.match.params.date}</h2>
)
}
}
https://reacttraining.com/react-router/web/api/match
According to the answer in:
Dynamic imports in ES6 with runtime variables
"The rules for import() for the spec are not the same rules for Webpack itself to be able to process import()".
So no you can't use variables with webpack dynamic import statements.
It doesn't work directly to use the variable but could be used as follows -
const path = './test.jpg';
import(`${path}`);