Home > other >  React map function gives back same image when mapping random generated image url
React map function gives back same image when mapping random generated image url

Time:11-24

I'm mapping a simple array of team member data. The image url in the data is a random generated cat picture. My problem is that when I map over the array of teammembers, the image of all members is the same. Every time I refresh they all change to another image, but not a different one for each member.

The rest of the data works fine. How can I resolve this?

Example of the data:

[
  {
    "name": "Jessika",
    "role": "Interaction Design",
    "location": "berlin",
    "image": "https://loremflickr.com/640/480/cat",
    "tags": [
      "salmon",
      "red"
    ]
  },
  {
    "name": "Kyra",
    "role": "Project Manager",
    "location": "amsterdam",
    "image": "https://loremflickr.com/640/480/cat",
    "tags": [
      "white",
      "gold"
    ]
  },

My code:

        <div className="grid-item">
          {response && (
            <div className="card">
              {response.map((member: any) => {
                return (
                  <div key={member.name} className="card__container">
                    <div className="card-image">
                      <img src={member.image} alt="Team member" />
                    </div>
                    <div className="card-content">
                      <p>{member.name}</p>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

I tried mapping my response and displaying the data in my jsx. It works fine but the image won't give a unique image for each team member.

const { useState } = React;

const Example = () => {
    const response = [
        {
            name: "Jessika",
            role: "Interaction Design",
            location: "berlin",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["salmon", "red"],
        },
        {
            name: "Kyra",
            role: "Project Manager",
            location: "amsterdam",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["white", "gold"],
        },
    ];

    return (
        <div className="grid-item">
            {response && (
                <div className="card">
                    {response.map((member/*: any*/) => {
                        return (
                            <div key={member.name} className="card__container">
                                <div className="card-image">
                                    <img src={member.image} alt="Team member" />
                                </div>
                                <div className="card-content">
                                    <p>{member.name}</p>
                                </div>
                            </div>
                        );
                    })}
                </div>
            )}
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

CodePudding user response:

Since the URLs are the same, the browser may re-use the previous response when two requests are made at almost exactly the same time. To prevent that, add a query string to make them unique so the browser doesn't reuse the response:

<img src={member.image   "?"   member.name} alt="Team member" />

const { useState } = React;

const Example = () => {
    const response = [
        {
            name: "Jessika",
            role: "Interaction Design",
            location: "berlin",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["salmon", "red"],
        },
        {
            name: "Kyra",
            role: "Project Manager",
            location: "amsterdam",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["white", "gold"],
        },
    ];

    return (
        <div className="grid-item">
            {response && (
                <div className="card">
                    {response.map((member/*: any*/) => {
                        return (
                            <div key={member.name} className="card__container">
                                <div className="card-image">
                                    <img src={member.image   "?"   member.name} alt="Team member" />
                                </div>
                                <div className="card-content">
                                    <p>{member.name}</p>
                                </div>
                            </div>
                        );
                    })}
                </div>
            )}
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

I've used the member name there, but it may not be appropriate to send that information to the image server. It just needs to be something that's unique to that member and, ideally, doesn't change over time (so ideally, not a random number, though if the image is always meant to be re-fetched, that would be okay).

Or perhaps the member index (since this isn't a React key):

{response.map((member/*: any*/, index/*: number*/) => {
    return (
        <div key={member.name} className="card__container">
            <div className="card-image">
                <img src={member.image   "?"   index} alt="Team member" />
            </div>
            <div className="card-content">
                <p>{member.name}</p>
            </div>
        </div>
    );
})}

const { useState } = React;

const Example = () => {
    const response = [
        {
            name: "Jessika",
            role: "Interaction Design",
            location: "berlin",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["salmon", "red"],
        },
        {
            name: "Kyra",
            role: "Project Manager",
            location: "amsterdam",
            image: "https://loremflickr.com/640/480/cat",
            tags: ["white", "gold"],
        },
    ];

    return (
        <div className="grid-item">
            {response && (
                <div className="card">
                    {response.map((member/*: any*/, index/*: number*/) => {
                        return (
                            <div key={member.name} className="card__container">
                                <div className="card-image">
                                    <img src={member.image   "?"   index} alt="Team member" />
                                </div>
                                <div className="card-content">
                                    <p>{member.name}</p>
                                </div>
                            </div>
                        );
                    })}
                </div>
            )}
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>


If the image URL may already have a query string, you'll want & instead of ?. You could do:

function appendUrlPart(url, part) {
    const delim = url.includes("?") ? "&" : "?";
    return url   delim   encodeURIComponent(part);
}

...then src={appendUrlPart(member.image, index)}.


In a comment you've said this is for an assignment and the URL is given as part of the assignment. Unless the assignment is intended to get you to solve this very problem (that is, if you think the instructor just threw out a URL without considering this possible issue), you might just use other URLs from that server in the "response" data, rather than adding the code above. The code above solves the problem, but if it's not a real problem, you don't want unnecessary code in your solution. Perhaps just use https://loremflickr.com/640/480/cat, https://loremflickr.com/640/480/dog, https://loremflickr.com/640/480/giraffe, etc.; or even just https://loremflickr.com/640/480/cat?1, https://loremflickr.com/640/480/cat?2, https://loremflickr.com/640/480/cat?3 etc. Along with a comment explaining why you did that.

  • Related