0

From reading the nextjs documentation the getStaticProps should pre-render data that I want before a user comes to my site. I am trying to get images before I load them onto cards.

Here in my index.js

 export async function getStaticProps() {
    const images = getImages();
    return {
        props: {
            data: await Promise.all(images), // wait for all images to load
        }, revalidate: 5
    };
}

The getImages function looks like this

export function getImages() {
    const frameCount = 39;
    const data = [];
    for (let id = 0; id <= frameCount; id++) {
        // add new promise to array
        data.push(
            fetch(`http://localhost:3000/GeneratedImgs/${id}.png`).then(
                (res) => res.url
            )
        );
    }
    return data;
}

So then in the index.js I pass that data into a component which passes it into another component to the next/image.

export default function Home({ data }) {
    
    let testCardGrid = <div className="loading"></div>;
    if (data !== null) {
        mouseCardGrid = <CardGrid data={data} />;
    }

    return (
        <>
            <Head>
                <title>Mouse</title>
                <meta name="description" content="Generated by create next app" />
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <Header />
            {testCardGrid}
            <Map />
        </>
    );
}

CardGrid.js looks like this:

export default function CardGrid({ data }) {
    let cardArray = [];
    let randomNumbers = [];

    function getRandomInts(quantity, max) {
        const arr = [];
        while (arr.length < quantity) {
            var candidateInt = Math.floor(Math.random() * max) + 1;
            if (arr.indexOf(candidateInt) === -1) arr.push(candidateInt);
        }
        return arr;
    }

    randomNumbers = getRandomInts(8, 40);
    randomNumbers.forEach((num) => {
        cardArray.push({
            title: `Card#${num}`,
            imageUrl: data[num]
        });
    });

    useEffect(() => {
        console.log("cardgrid triggered");
    }, []);
    return (
        <section id="content" className="section-padding">
            <div className="container-fluid">
                <div className="row">
                    {cardArray.map((object) => (
                        <Card title={object.title} imageUrl={object.imageUrl} />
                    ))}
                </div>
            </div>
        </section>
    );
}

Finally the Card.js file looks like this:

export default function Card({ title, imageUrl }) {
    useEffect(() => {
        console.log("card added");
    }, []);

    return (
        <div className="col-lg-3 col-sm-6">
            <div className="card text-center">
                <Image
                    priority
                    className="card-img-top"
                    src={imageUrl}
                    height={300}
                    width={300}
                />

                <div className="card-body">
                    <h2 className="card-text">{title}</h2>
                </div>
            </div>
        </div>
    );
}

After I refresh the page a couple of times or when I go to a differnt page on the site and come back to the home page it will give me the error:

Unhandled Runtime Error Error: Image is missing required "src" property. Make sure you pass "src" in props to the next/image component. Received: {"width":300,"height":300}

I was trying to show a loading div if the data was null and thought I could try the revalidate attribute the getStaticProps() method has but it too was giving me the same error.

So, I am not sure I understand this because I thought that the getStaticProps would always get the images before the page loads. I see in the docs that it says it runs under next build. So is it just once and done? Am I missing a fundamental concept of pre-rendering? please give me your advice.

3

1 Answer 1

2

I think these this correction shoukd be done in getImages:

export function getImages() {
  const frameCount = 39;
  const data = [];
  for (let id = 0; id <= frameCount; id++) {
     // change this to

     data.push(`http://localhost:3000/GeneratedImgs/${id}.png`);
  }
  return data;
}

Also, when trying to test getRandomInts one of the results was 40 which will be undefined, so maybe you should change it to the below:

// remove + 1
// It's also recommended to use `let` instead of `var`
let candidateInt = Math.floor(Math.random() * max);
Sign up to request clarification or add additional context in comments.

2 Comments

Yep it was the 40 that was causing the error! Damn, thank you!
@kpgabriel you're welcome and glad to help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.