skip to Main Content

I’ve looked everywhere for answers regarding this and found none.

I have a simple functional component in React below.

There are some images in src/images that im trying to import without manually writing a bunch of import statements, one for each picture, like we’d import useEffect etc. Thats because this component will be called for many items so I want a way to dynamically import one of those images

props.item.imageSource is a relative path that has the EXACT same value as the string i hardcoded in the snipped below this one. I’ve checked with React’s debugging tools for the browser. This gives me a "Cannot find module" error. Ive tried without "" + too.

function MenuItemCard(props) {
  const [importedImage, setImportedImage] = useState(null);

  useEffect(() => {
    import("" + props.item.imageSource).then((image) =>
      setImportedImage(image.default)
    );
  }, []);

  return (
    <div className="menuItemCard">
      {importedImage && <img src={importedImage} />}
    </div>
  );
}

However this works when hardcoding the path

function MenuItemCard(props) {
  const [importedImage, setImportedImage] = useState(null);

  useEffect(() => {
    import("../../images/burgers/burger-1.png").then((image) =>
      setImportedImage(image.default)
    );
  }, []);

  return (
    <div className="menuItemCard">
      {importedImage && <img src={importedImage} />}
    </div>
  );
}

Ive tried saving the imageSource value in another variable and passing that to import, with/without "" +, none work so I’m guessing its not specifically something to do with my props rather how I’m using the variables. The only thing that works is passing in the hardcoded string directly into import.

Similar issue with using require. This doesnt work

return (
    <div className="menuItemCard">
      <img src={require(props.item.imageSource)} />
    </div>
  );

But this does

return (
        <div className="menuItemCard">
          <img src={require("../../images/burgers/burger-1.png")} />
        </div>
      );

2

Answers


  1. Is there a reason you do import for images?

    If the image url is in the props, you can just do it like this: https://codesandbox.io/s/dynamic-images-dyzsr1

    also do take a look at the actual component -> https://codesandbox.io/s/dynamic-images-dyzsr1?file=/src/components/MenuItemCard.js

    you don’t even need useEffect or state there

    if your data looks something like this:

    const propsData = {
      item: {
        imageSource:
          "https://images.unsplash.com/photo-1586190848861-99aa4a171e90?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=880&q=80"
      }
    };
    

    then your component might look like this:

    import React from "react";
    
    function MenuItemCard(props) {
      const { imageSource } = props.item;
    
      return (
        <div className="menuItemCard">
          {imageSource && (
            <img alt="presentation of various food" src={imageSource} />
          )}
        </div>
      );
    }
    
    export default MenuItemCard;
    

    EDIT:

    If you are trying to import hundreds of images, check this answer out: https://stackoverflow.com/a/48121563/3407499

    I just updated code sandbox example that I posted above, you can check that setup that will allow you to use the relative paths for images

    Login or Signup to reply.
  2. As was mentioned in the comments, CRA uses webpack under the hood, so require.context can be used easily.

    require.context(
      directory,
      (useSubdirectories = true),
      (regExp = /^./.*$/),
      (mode = 'sync')
    );
    
    

    Assuming you have a directory called images in the src directory, you could do the following to import all of the images in the directory and map over them to output them:

    
    // use require.context and pass the directory
    // returns a function with 3 properties: resolve, keys, id
    const images = require.context('./images');
    
    export default function App() {
    // images.keys() returns an array of the modules (matching files)
    // which can be mapped and then resolved by passing the 
    // individual file id back to the images function:
    
      return (
        <main>
          {!!images.keys().length &&
            images
              .keys()
              .map(mod => <img src={images(mod)} key={mod} alt="" />)}
        </main>
      );
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search