skip to Main Content

Should it be simple? One component, one .json file, multiple objects, and a prop to return one of these objects. Honestly not sure if a prop can be passed this way?

Card Component

Currently, this is showing the featured array just fine via cardsData.featured.map.

import './Card.scss';
import cardsData from '../../assets/dataNew';

const Card = () => {
    return (
        <>
            {cardsData.featured.map((card, i) => {
                let cardLink = card.links.linkOne;
                return (
                    <div key={i} className="card">
                        <h1>{props.foo}</h1>
                        <div className="card__image">
                            <picture>
                                <source
                                    media="(max-width: 767px)"
                                    srcSet={card.smallImg}
                                />
                                <img src={card.largeImg} alt="" />
                            </picture>
                        </div>
                        <div className="card__title">{card.title}</div>
                        <div className="skills">
                            {card.skills.map((skill, i) => {
                                return <span key={i}>{skill}</span>;
                            })}
                        </div>
                        <ul className="card__links">
                            <li>
                                <a
                                    target="_blank"
                                    href={card.links.linkOne}
                                    className="underline-hover">
                                    View project
                                </a>
                            </li>
                            {cardLink && (
                                <li>
                                    <a
                                        target="_blank"
                                        href={card.links.linkTwo}
                                        className="underline-hover">
                                        View code
                                    </a>
                                </li>
                            )}
                        </ul>
                    </div>
                );
            })}
        </>
    );
};

export default Card;

Data

The featured object has 4 items total, and the standard has 10 total but will increase over time.

{
    "featured": [
        {
            "title": "Designo",
            "largeImg": "./img/thumbnail-project__14-lg.webp",
            "smallImg": "./img/thumbnail-project__14-sm.webp",
            "skills": ["SCSS", "HTML", "React.js"],
            "links": {
                "linkOne": "https://satrop.github.io/Designo/",
                "linkTwo": "https://github.com/satrop/Designo"
            }
        },
        {
            ...
        }
    ],
    "standard": [
        {
            "title": "Audiophile",
            "largeImg": "./img/thumbnail-project__10-lg.webp",
            "smallImg": "./img/thumbnail-project__10-sm.webp",
            "skills": ["SCSS", "HTML", "React.js"],
            "links": {
                "linkOne": "https://satrop.github.io/audiophile/#/",
                "linkTwo": "https://github.com/satrop/audiophile"
            }
        },
        {
            ...
        }
    ]
}

I initially thought that I could pass a prop link this…

const Card = (props) => {
    return (
        <>
            {cardsData[props.category].map((card, i) => {
                ...

And grabbing it on the other side like this…

<Cards category="featured" />

I just get "Cannot read properties of undefined (reading ‘map’)" error.

I’m not sure what to look for to get what I want.

2

Answers


  1. I created an oversimplified sandbox using your example

    codesandbox

    It seems to work just fine. You can also set "standard" in App.js and verify that the page updates.

    Can you see any difference to your local code?

    Login or Signup to reply.
  2. To achieve this you have to render the Card component when mapping the data.

    //get the data coming from App(Parent) as a props(destructuring)
    function Card({title, smallImg, largeImg, skill, links}) {
        return (
            <>
                <div className="card">
                    <h1>{title}</h1>
                    <div className="card__image">
                        <picture>
                            <source
                                media="(max-width: 767px)"
                                srcSet={smallImg}
                            />
                            <img src={largeImg} alt="" />
                        </picture>
                    </div>
                    <div className="card__title">{title}</div>
                    <div className="skills">
    //never use the index as key because can cause flickering when manipulate the array
                        {skill.map((skill, i) => {
                            return <span key={skill}>{skill}</span>;
                        })}
                    </div>
                    <ul className="card__links">
                        <li>
                            <a
                                target="_blank"
    //when work with object is recomended to use obj?.wherever to void crash if the key does exist
                                href={links?.linkOne}
                                className="underline-hover">
                                View project
                            </a>
                        </li>
                        {links?.linkTwo && (
                            <li>
                                <a
                                    target="_blank"
                                    href={links.linkTwo}
                                    className="underline-hover">
                                    View code
                                </a>
                            </li>
                        )}
                    </ul>
                </div>
            </>
        )
    }
    
    export default function App() {
        const cardData = [
            {
                title: 'card 1',
                smallImg: '../src/bg_4_colors.png',
                largeImg: '../src/bg_4_colors.png',
                links: {
                    linkOne: "https://satrop.github.io/audiophile/#/",
                    linkTwo: "https://github.com/satrop/audiophile"
                },
                skills: ['skill_1', 'skill_2', "skill_3"]
            },
            {
                title: 'card 2',
                smallImg: '../src/bg_4_colors.png',
                largeImg: '../src/bg_4_colors.png',
                links: {
                    linkOne: "https://satrop.github.io/audiophile/#/",
                    linkTwo: "https://github.com/satrop/audiophile"
                },
                skills: ['skill_1', 'skill_2', "skill_3"]
            }
        ]
        return (
            <div>
                {cardData.map(item =>
                    <Card
                        key={item.title}
                        title={item.title}
                        smallImg={item.smallImg}
                        largeImg={item.largeImg}
                        links={item.links}
                        skill={item.skills}
                    />
                )}
            </div>
        );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search