zoran lazarevic
zoran lazarevic

Reputation: 81

render multiple images in React using map

i have objects with keys img and the value is relative path to image folder placed in src folder '/images'. I'm using map to loop over destructured data and adding it to DOM with simple template like this:

<div key={id}>

<img src={img + '.jpg'} alt='{title}' />
</div>

And my data object looks like this:

const category = [
  {
    id: 1,
    title: 'cizme',
    img: './images/cizme',
    link: './cizme'},
...

data(category) is defined in App component

import data from './data';
import Home from './Home';
import logo from './images/logo_fin-01.png';

import Navbar from './Navbar';

function App() {
  return (
    <div className='App'>
      <Navbar logo={logo} />
      <Home data={data} />
    </div>
  );
}

export default App;

and Home comp is:

const Home = ({ data }) => {
  return (
    <div className='kat'>
      {data.map(({ id, title, img, link }) => (
        <li key={id}>
          <span>{title}</span>
          <div className='img-container'>
            <img src={img + '.jpg'} alt={title}></img>
          </div>
        </li>
      ))}
    </div>
  );
};

export default Home;

Now, and in browser paths are displayed correctly, with no errors, but it says image 'could not load the image'.I tried to copy images folder to public but then i get error 'its out of scope or sth like this(i forgot)'.So what should i do?

update: require() works in sandbox, localy doesn't.

https://codesandbox.io/embed/zealous-christian-0j3v3?fontsize=14&hidenavigation=1&theme=dark

Upvotes: 1

Views: 6619

Answers (2)

Areeb Khan
Areeb Khan

Reputation: 413

Your current approach won't work (unless you have to import the images over a loop), since you've kept these images in src folder. By keeping the image url as relative to the current folder won't work, because when passing a URL to src (and not an imported image), your browser starts rendering, the img's src attribute will look with respect to the URL, and not the folder from which the javascript file is being loaded and executed.

In other words, if my component serving this mapped image route is at the URL xyz.com/something/currentScreen, then './images/cizme' + '.jpg' will translate to xyz.com/something/images/cizme.jpg, which doesn't exist.

Since you are trying to dynamically render these images, a good way would be to place them in public folder, (and then inside 'images' folder, since your URL says so), and then have '/images/cizme' + '.jpg' which will result in xyz.com/images/cizme.jpg loading properly, because they exist inside the public folder.

Edit: Can you confirm that your browser paths are correct? Try opening Network Tab as prescribed in the comments.

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 203408

I'm assuming that since your category array is specifying local/relative paths that it's generated at compile time (and not some dynamic value at run-time), and as such, will have access to assets located in the src source directory.

You can either import all the images and specify them in the category array.

import img1 from './images/cizme.jpg';
...

const category = [
  {
    id: 1,
    title: 'cizme',
    img: img1,
    link: './cizme'
  },
...

Or since listing all the imports explicitly is impractical, you can just require them in the data.

const category = [
  {
    id: 1,
    title: 'cizme',
    img: require('./images/cizme.jpg'),
    link: './cizme'
  },
...

Then you can just render the images as per normal.

{category.map(({ id, img, title}) => (
  <div key={id}>
    <img src={img} alt='{title}' />
  </div>
))}

Update

I updated my linked codesandbox to reflect your code. If the exported data uses require to pull in the images, then Home can simply attach the img value to the src attribute.

const Home = ({ data }) => {
  return (
    <div className="kat">
      {data.map(({ id, title, img, link }) => (
        <li key={id}>
          <span>{title}</span>
          <div className="img-container">
            <img src={img} alt={title}></img>
          </div>
        </li>
      ))}
    </div>
  );
};

Edit sharp-stonebraker-wm2op

Example with cat1.jpg, cat2.jpg, and cat3.jpg images located in a "./images" directory in src.

enter image description here

Code:

data.js

const data = [
  {
    id: 1,
    title: "cizme",
    img: require("./images/cat1.jpg"),
    link: "./cizme"
  },
  {
    id: 2,
    title: "cizme",
    img: require("./images/cat2.jpg"),
    link: "./cizme"
  },
  {
    id: 3,
    title: "cizme",
    img: require("./images/cat3.jpg"),
    link: "./cizme"
  }
];

export default data;

App.js

import data from "./data";

const Home = ({ data }) => {
  return (
    <div className="kat">
      {data.map(({ id, title, img, link }) => (
        <li key={id}>
          <span>{title}</span>
          <div className="img-container">
            <img src={img} alt={title}></img>
          </div>
        </li>
      ))}
    </div>
  );
};

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Edit to see some magic happen!</h2>

      <Home data={data} />
    </div>
  );
}

Upvotes: 0

Related Questions