typeError: Cannot read property 'map' of undefined (nextjs)

Viewed 2550

I tried very hard to find a solution to this problem, but I didn't find anything, could anyone help?

I just want to fetch this data.

typeError: Cannot read property 'map' of undefined -> Error

import styles from '../styles/galery.module.css'
import Image from 'next/image'
import Link from 'next/link'
import photo from '../public/01.png'

export const getStaticProps = async () => {

    const response = await fetch('https://api.github.com/orgs/rocketseat');
    const data = await response.json();

    return {
        props: { mods: data }
    }
}

const ProjectLines = ({ mods }) => {
    return (
        <div className={styles.categoryWrapper}>
            <h4 className={styles.subTitle}>Escritório</h4>
            <div className={styles.lineWrapper}>
                <a className={styles.leftArrow}>&#10094;</a>
                <div className={styles.line}>
                    {mods.map(mod => (
                        <div className={styles.imageBox}>
                            <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
                            <div className={styles.linkContent}>
                                <span className={styles.name}>{mod.login}</span>
                                <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
                            </div>
                        </div>
                    ))}
                </div>
                <a className={styles.rightArrow}>&#10095;</a>
            </div>
        </div>
    );
}
export default ProjectLines;
6 Answers

Yow all this comments all they do is confusing. The solution is very simple right before you map them mods check if they exists how ?

{mods && mods.map(.....

That's one way or the other is to add a default value

({ mods = []}) =>

But do the first one, is better

I was trying to use getStaticProps in a component archive, it need to be used in a page... Thanks everyone.

NextJS Documentation

well, the error is simple basically the response that you are getting is a json object, a plain json object.

with this said, basically you can not map over a object or well, you can but not using map.

the response of the url is

{
    login: "Rocketseat",
    id: 28929274,
    node_id: "MDEyOk9yZ2FuaXphdGlvbjI4OTI5Mjc0",
    url: "https://api.github.com/orgs/Rocketseat",
    repos_url: "https://api.github.com/orgs/Rocketseat/repos",
    events_url: "https://api.github.com/orgs/Rocketseat/events",
    hooks_url: "https://api.github.com/orgs/Rocketseat/hooks",
    issues_url: "https://api.github.com/orgs/Rocketseat/issues",
    members_url: "https://api.github.com/orgs/Rocketseat/members{/member}",
    public_members_url: "https://api.github.com/orgs/Rocketseat/public_members{/member}",
    avatar_url: "https://avatars.githubusercontent.com/u/28929274?v=4",
    description: "Plataforma de educação em tecnologia ",
    name: "Rocketseat",
    company: null,
    blog: "https://rocketseat.com.br",
    location: null,
    email: "opensource@rocketseat.com.br",
    twitter_username: "rocketseat",
    is_verified: true,
    has_organization_projects: true,
    has_repository_projects: true,
    public_repos: 23,
    public_gists: 0,
    followers: 0,
    following: 0,
    html_url: "https://github.com/Rocketseat",
    created_at: "2017-05-24T16:16:47Z",
    updated_at: "2021-10-04T18:42:26Z",
    type: "Organization"
}

so if you want to display only the login as I think you want you need to do this:

const ProjectLines = ({ mods }) => {
    return (
        <div className={styles.categoryWrapper}>
            <h4 className={styles.subTitle}>Escritório</h4>
            <div className={styles.lineWrapper}>
                <a className={styles.leftArrow}>&#10094;</a>
                <div className={styles.line}>
                    <div className={styles.imageBox}>
                        <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
                        <div className={styles.linkContent}>
                            <span className={styles.name}>{mod.login}</span>
                            <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
                        </div>
                    </div>
                </div>
                <a className={styles.rightArrow}>&#10095;</a>
            </div>
        </div>
    );
}

but if you want to loop over each key you should do this:

{Object.values(mods || {}).map(mod => (
    <div className={styles.imageBox}>
        <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
            <div className={styles.linkContent}>
                <span className={styles.name}>{mod}</span>
                <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
            </div>
    </div>
))}

hope it helps and you understand the issue with your code.

the url you are using here

(https://api.github.com/orgs/rocketseat)

to fetch data giving object in return and map functions are for array.

if you want to use the value remove the map and use the object itself.

<div className={styles.line}>
                        <div className={styles.imageBox}>
                            <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
                            <div className={styles.linkContent}>
                                <span className={styles.name}>{mods.login}</span>
                                <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
                            </div>
                        </div>
                </div>

just change this part and you are good to go.

You are fetching the data and passing it properly, but unfortunately, it is not an array, it's an object. The .map function is used on arrays to go through every element, almost like an forEach but here they are returned.

What you'll need to do is create a component for Organizations which will have the props from the object fetched, then the array of organizations will need to be traversed, if you want that.

You need to add verification for each value of const ProjectLines

You have now:

<div className={styles.line}>
                    {mods.map(mod => (
                        <div className={styles.imageBox}>
                            <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
                            <div className={styles.linkContent}>
                                <span className={styles.name}>{mod.login}</span>
                                <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
                            </div>
                        </div>
                    ))}
                </div>

You need to implement (for each variable you are using in return):

{mods ? 
<div className={styles.line}>
                    {mods.map(mod => (
                        <div className={styles.imageBox}>
                            <Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
                            <div className={styles.linkContent}>
                                <span className={styles.name}>{mod.login}</span>
                                <Link href=""><a className={styles.link}>Veja Mais!</a></Link>
                            </div>
                        </div>
                    ))}
</div>
: ''}

Why so? because of usage getStaticProps. It's async function, check properly docs.

Also for the .map function. Somebody tells that .map can be implemented with objects, that is true. !BUT! you have to console.log(typeof(mods)), and I am 90% sure you have it as array object. In any case, you have undefined value in mods, it means it's null, and not triggering "isObject" error.

Related