1

I'm working with next.js and trying to get images dynamically like this:

{list.map((prod) => (
      <div className={styles.singleProduct}>
          <h6>{prod.Brand.toUpperCase()}</h6>
          <p>{prod.ProductName}</p>
          <img
              src={require(`../public/assets/products/${prod.ProductName
              .replace(" ", "-")}.png`)}
           /> 
       </div>
  ))}
   

With this code I get the following error: "./public/assets/products/Product-One.png 1:0 Module parse failed: Unexpected character '�' (1:0)"

When I hard code the image everything works, f.ex.:

... 
<img
    src={require(`../public/assets/products/Product-One.png`)}
/> 
...

So I suppose that I get the error because of the dynamic variable?! Could someone help me with the issue? Thanks a lot!

Ewax_Du
  • 325
  • 1
  • 8
  • 22
  • Are you using a Webpack loader for images? – Alvaro Nov 28 '20 at 15:45
  • I'm using the default configuration for webpack from create-next-app. I'm new in development, so I didn't change anything. Here's a link that might help: https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config – Ewax_Du Nov 28 '20 at 16:47
  • And aditionally I'm using next-images: https://www.npmjs.com/package/next-images – Ewax_Du Nov 28 '20 at 17:10
  • It looks like the problem comes from Webpack not recognizing images because it is missing a loader for them. As far as I understand this kind of loader is included when calling the function from the next-images package; from the docs: `const withImages = require('next-images');module.exports = withImages();`, did you include this in `next.config.js`? PD: Take a look at [next official Image component](https://nextjs.org/docs/api-reference/next/image) – Alvaro Nov 28 '20 at 17:21
  • Thanks! But yes, I have already added the code to next.config.js. I also tried to add some options from the lib, f.ex. like so: module.exports = withImages({ exclude: path.resolve(__dirname, 'src/assets/svg'), webpack(config, options) { return config } }). But it didn't work. Now I found this: https://stackoverflow.com/questions/44991669/react-native-require-with-dynamic-string. Maybe this could be an issue? – Ewax_Du Nov 28 '20 at 17:38
  • 1
    Could you try using strings: `require("../public/assets/products/" + prod.ProductName.replace(" ", "-") + ".png")` – Alvaro Nov 28 '20 at 17:43
  • Ok, so I tried different variations, but it doesn't work. For the code above I get this error: "Error: Module parse failed: Unexpected character '�' (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders" - so I think you are right with the webpack loaders. – Ewax_Du Nov 28 '20 at 18:16
  • 1
    Could you share next.config.js code? Not strictly related but the root element of .map is missing a key. Set one and see if it helps `
    `
    – Alvaro Nov 28 '20 at 18:26
  • Sorry, took me some time to get rid of the key-error. But also without the key-error: no changes. Here's the error from the console: "Uncaught Error: Cannot find module './Foaming-cleanser product name.png' ". This seems a little strange to me, because it should be: "...Foaming-cleanser-product-name.png". I doublechecked the names of the img and the name in DB, but everything is right. My next.config.js code: const withImages = require('next-images'); module.exports = withImages() – Ewax_Du Nov 28 '20 at 19:24
  • I see, there is an issue with the replace, it is only replacing the first match. Try with this: `prod.ProductName.replace(/ /g, "-")`. On a side note I would suggest only using initial capital letter for React components or JS classes. – Alvaro Nov 28 '20 at 19:45
  • Thx a lot! The replacement seem to work correctly now. But the main problem is still there :( Now, for every img I get the following error: "./public/assets/products/Foaming-cleanser-product-name.png 1:0 Module parse failed: Unexpected character '�' (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders (Source code omitted for this binary file)". So I might need to change the default webpack config? Or do you have other suggestions? – Ewax_Du Nov 28 '20 at 20:53
  • I believe we can be sure the loader is not being used. A silly question but, did you install `next-images` correctly and reset the server after changing `next.config.js`? At this point I am not sure I can help without seeing all the project code. Maybe someone else can help you better. One last question, you say if you hard-code the value it works correctly, it doesn't complain and the image is loading in the browser? – Alvaro Nov 28 '20 at 20:59
  • Yes, I think next-images is installed correctly (I see version ^1.6.2 in package.json). I have killed the server several times and restarted everything (also VSC). When I use f.ex. this code: everything works - the img is loaded in the browser. It is as if the dynamic variable isn't working. But I don't know how to change it. Anyway, if you have an other idea, please let me know :) Otherwise, thank you so much for your help with the other side-issues!! – Ewax_Du Nov 28 '20 at 21:18

2 Answers2

0

I was getting the same error for svg images so I use this package https://www.npmjs.com/package/react-inlinesvg. What this package does under the hood, it loads the image url during runtime as a data uri and then convert it to image format (in this case it does svg). After converting the image it uses the image as a react component and insert it as child.

Sonu Nigam
  • 279
  • 1
  • 7
0

So, with the help here especially from Alvaro I finally have the solution. The following code works:

src={`/assets/products/${prod.ProductName.replace(/ /g, "-")}.png`} 

or

src={"/assets/products/" + prod.ProductName.replace(/ /g, "-") + ".png"} 

It seems as "require" doesn't work well with variables.

Ewax_Du
  • 325
  • 1
  • 8
  • 22
  • I'm glad you could solve it. For reference, the reason for setting a known path in the begining of the require path, and possibly using string for this case is explained [here](https://stackoverflow.com/a/37228426). – Alvaro Nov 29 '20 at 18:46