0

I am attempting to write a function that will return a value for a srcSet attribute, but I am running into an error where React cannot find the image module when required inside a function:

// Error: Cannot find module './img/logo.png'

function App() {

  const getSrcSet = ( src ) => {
    const ext = '.' + src.split('.').pop();
    const _2x = src.replace(ext,'') + '@2x' + ext;

    var img1 = require(src).default // ERROR OCCURS HERE
    var img2 = require(_2x).default

    return img1 + ' 1x, ' + img2 + ' 2x';
  }

  return (
    <img src={require('./img/logo.png').default} srcSet={getSrcSet('./img/logo.png')} alt="logo" />
  );

}

--

The function works as expected when I use the "PUBLIC_URL" instead of "require()", but I would prefer to use the former solution if it's possible:

const publicUrl = process.env.PUBLIC_URL

function App() {

  const getSrcSet = ( src ) => {
    const ext = '.' + src.split('.').pop();
    const _2x = src.replace(ext,'') + '@2x' + ext;

    return src + ' 1x, ' + _2x + ' 2x';
  }

  return (
    <img src={publicUrl+'img/logo.png'} srcSet={publicUrl+'img/logo.png'} alt="logo" />
  );

}

--

NOTE:

I am well aware that I can use the following solution, but I would love to use the getSrcSet function if possible:

import logo from 'logo.png'
import logo2 from 'logo@2x.png'

function App() {

  return (
    <img src={logo} srcSet={logo + ' 1x, ' + logo2 + ' 2x'} alt="logo" />
  );

}

EDIT: Typos

EDIT 2: Added in error message

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
mdurchholz
  • 523
  • 1
  • 4
  • 16
  • Usually, errors provide information about what went wrong. Without the error message, one can only guess what went wrong. – Konrad Jul 13 '22 at 19:16
  • I mentioned the error: "Error: Cannot find module './img/logo.png'". I can confirm that the path is fine because I can require outside of the function and have it work as expected. – mdurchholz Jul 13 '22 at 19:47
  • So why don't you use `require` outside the function to get the image? I see you are using `import`, but that's not the same as `require` – Konrad Jul 13 '22 at 19:50
  • I am more so trying to see if this is even possible. I would love to have a function that can dynamically require images without having to create a variable for every image instance. – mdurchholz Jul 13 '22 at 19:53
  • The images you import are changed in a build time to URLs and then moved to the build directory. So if you don't do this, they will not be moved and can't be accessed. The entire public folder is moved anyway, so you can always access it. – Konrad Jul 13 '22 at 19:59
  • Please do not edit solution announcements into the question. Accept (i.e. click the "tick" next to it) one of the existing answer, if there are any. You can also create your own answer, and even accept it, if your solution is not yet covered by an existing answer. Compare https://stackoverflow.com/help/self-answer – Yunnosch Jul 13 '22 at 21:23

1 Answers1

0

I believe I found a solution to my issue. I used a combination of the following posts:

https://stackoverflow.com/a/46079722/2440863

https://stackoverflow.com/a/48264153/2440863

--

[./components/Image.js]

const images = require.context('../img', true)
const image = (path) => images(`./${path}`).default

const getSrcSet = ( src ) => {
  let srcset = image(src) + ' 1x';

  const ext = '.' + src.split('.').pop()
  const _2x = src.replace(ext,'') + '@2x' + ext

  try {
    return srcset + image(_2x) + ' 2x'
  } catch (err) {
    return null
  }
}

function Image (props) {
  var { src, alt, ...other } = props;

  return (
    <img src={image(props.src)} srcSet={getSrcSet(props.src)} alt={props.alt} {...other} />
  )

}

export default Image

[./App.js]

import Img from './components/Image'

function App() {

  return (
    <Img src="logo.png" alt="logo" data-foo="bar" />
  );

}

export default App;

EDIT: Typo

mdurchholz
  • 523
  • 1
  • 4
  • 16