Avoid Pitfalls when Using Images in React
June 21, 2022
3 min read
Michael P. McAuliffe
Which module loading solution works best for your situation?
When React code is transpiled into browser-readable javascript, JSX goes through a few transformations before it is seen in the browser. Build directories are restructured and files are indexed differently in production. This transformation exposes the possibility of hazards when dealing with different types of modules.
Developers use toolchains such as Create React App (CRA), and Next.js use Webpack as a bundler to assist with module integration. There are minor differences between versions of Webpack and CRA that affect the src attribute in an image tag. Aside from those minor tweaks, there are 3 main ways to utilize an image in React.
- Import an image as a module
- Require an image inline
- Accessing images in the public directory, the 'escape hatch'
Import an Image as a Module
Once the image is imported, the imported variable can be set as the value of the src attribute in an image tag.
1import beautifulMountians from './images/beautifulMountians.jpg';23const FavoriteImages = () => (4 <>5 <p>My Favorite Mountian!</p>67 <img8 alt='beautiful-mount'9 src={beautifulMountians} />10 </>11);1213export default FavoriteImages;
My Favorite Mountian!
Considerations for Importing an Image
This is an easy way to display an image, but this wouldn't be practical for importing many images. This method also has limitations for displaying images dynamically. There are other solutions to these problems coming up.
Require an image inline
1const FavoriteImages = () => (2 <>3 <p>My Favorite Mountian!</p>45 <img6 alt='beautiful-mount'7 src={require('./images/beautifulMountians.jpg')} />8 </>9);1011export default FavoriteImages;
There may be issues using require in this way. Specific to older versions of react scripts, you may need to reference the .default key. You can read more about this issue here.
1<img2 alt='beautiful-mount'3 src={require('./images/beautifulMountians.jpg').default} />
You Actually CAN Import Multiple Images
Javascript modules are robust so there are many ways they can be used to overcome challenges. The power of import can be combined with the power of require. Take this file tree, for instance:
1├── src/2 ├── images/3 │ ├── bear1.jpg4 │ ├── bear2.jpg5 │ └── index.js6 ├── App.js7 └── …
Images can be exported as an object in images/index.js
1// index.js2 const images = {3 bear1: require('../images/bear1.jpg'),4 bear2: require('../images/bear2.jpg'),5 }67 export default images
The images object may now be imported in App.js.
1import images from './images';23const FavoriteImages = () => (4 <>5 <p>BEARS!</p>67 <img8 alt='bear1'9 src={images.bear1} />10 <img11 alt='bear2'12 src={images.bear2} />13 </>14);1516export default FavoriteImages;
Bears!
Using the Public Directory — The Escape Hatch
This option works with CRA and Next.js. CRA refers to this as an escape hatch and emphasizes that it should be used rarely. The file tree may be different in your app, but the premise is the same.
1├── public/2 ├── images/3 └── spookyTown.jpg4├── scr/5 ├── App.js6 └── …
The public directory can be accessed using the process.env.PUBLIC_URL environment variable.
1const FavoriteImages = () => (2 <>3 <p>Spooky Town</p>45 <img6 alt='spooky-town'7 src={process.env.PUBLIC_URL + '/images/spookyTown.jpg'} />8 </>9);1011export defualt FavoriteImages;
Spooky Town
More Blogs
Jazz-Up Your Buttons with Gradients
June 1, 2022