Next.js 13 waiting for data before loading anything
Unanswered
Channel catfish posted this in #help-forum
Channel catfishOP
Hi,
Ideally, I want my page to load content as it comes in view rather than waiting to load and displaying it all at once. How can this be achieved? Why does Next.js wait until all of the content is loaded from the data set before popping into view?
Ideally, I want my page to load content as it comes in view rather than waiting to load and displaying it all at once. How can this be achieved? Why does Next.js wait until all of the content is loaded from the data set before popping into view?
135 Replies
Channel catfishOP
"use client";
import Image from "next/image";
import { motion } from "framer-motion";
import { useEffect } from "react";
import styles from "/app/works/[project]/project.module.scss";
export default function Slides({
project,
activeSection,
setActiveSection,
scrollRef,
importedImages,
}) {
return (
<main className={styles.main} ref={scrollRef}>
{project.content.map((section, index) => {
const importedImage = importedImages.find(
(image) => image.index === index
);
return (
<section key={index} id={index} className={styles.section}>
<motion.div
onViewportEnter={() => setActiveSection(index)}
initial={{ opacity: 0, scale: 0.75 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
className={styles.section__content}
>
{section.type === "heading" && <h1>{section.body}</h1>}
{section.type === "paragraph" && <p>{section.body}</p>}
{section.type === "image" && (
<Image
src={importedImage.data}
alt="Image"
width={800}
height={800}
style={{
width: "100%",
height: "auto",
borderRadius: "0.5rem",
}}
placeholder="blur"
/>
)}
{section.type === "video" && (
<div className={styles.videoWrapper}>
<video
style={{ width: "100%", height: "100%" }}
controls
src={`https://stream.mux.com/${section.playbackID}/high.mp4`}
/>
</div>
)}
</motion.div>
</section>
);
})}
</main>
);
}Is it the way I'm importing data? should I be using fetch? I have a data.json file I am using.
`
export default async function Home({ params }) {
const { project: projectUrl } = params;
const project = data.find((project) => project.url === projectUrl);
const importedImages = await importAllImages(project);
if (!project) {
return <div>Project not found</div>;
}
return <Body {...{ project, importedImages }} />;
}`I'm assuming I should be using fetch() to get it from an api route instead of directly loading it?
Vespid wasp
unless you want to implement some kind of file streaming, or fetching some custom way of loading a range of bytes (and good luck parsing the partial json, of course it's doing to need to load all the data.json before it can start mapping
This is kind of a loaded question (pun intended) but I wonder if what you want to use is loading.tsx
like this example
check out this video here for how he accomplished that
if all you are talking about is waiting to load the images until tjhey come into view you want to look into "lazy loading"
oh hmm, defaults to lazy
Channel catfishOP
Hey, I have some resources related to this do you think you could help me understand if this will work?
Vespid wasp
maybe i'm not understading the problem, and i'm probably talking out of turn because I'm still learning next myself
Channel catfishOP
- Static Generation (getStaticProps) with diagram: https://nextjs.org/learn/basics/data-fetching/with-data
- Static Data Fetching in Next.js 13 (fetch()) https://nextjs.org/docs/getting-started/react-essentials
- Load Data from File: https://vercel.com/guides/loading-static-file-nextjs-api-route
- Static Data Fetching in Next.js 13 (fetch()) https://nextjs.org/docs/getting-started/react-essentials
- Load Data from File: https://vercel.com/guides/loading-static-file-nextjs-api-route
Check out the first link in that
Specifically this diagram
In my data I have text, images, video (its a portfolio site)
Vespid wasp
I'll check it out in the interest of learning but cant promise I'll be of much help
Channel catfishOP
damn aight
but basically my idea is to render in the data like getStaticProps but using next.js 13 fetch() instead
hopefully this fixes it but im not sure
Vespid wasp
is this json file dynamic? or will be it updated dynamically/regularly
Channel catfishOP
I want it to render in the text right away, but then images / video to be loaded in when the user is scrolling by it
Its static like I write it myself and it will be available at build time
ill show you an example of one objec
Vespid wasp
so as far as the images and videos loading when you're scrolling
Channel catfishOP
`
{
"title": "Amoeba",
"url": "amoeba",
"date": "2021",
"medium": ["3D", "Digital Fashion", "Animation", "AR"],
"technology": ["Blender", "SparkAR"],
"credits": [
{ "role": "3D, Animation & AR Filter", "name": "Christopher Ha" }
],
"links": [
{
"title": "Instagram AR Filter",
"url": "https://www.instagram.com/ar/1507397399653519/"
}
],
"content": [
{
"type": "heading",
"body": "An experimental digital eyewear animation and augmented reality filter blurring the lines between nature and technology."
},
{
"type": "video",
"playbackID": "m45ijzpnZhKLwWziI8X023aoMj6L2z7JMhz02MbNRntDQ"
},
{
"type": "video",
"playbackID": "Da1HldwcxwfHCn1xLFp2NoAbyMG00diHfJfpYWOnwrNc"
},
{
"type": "image",
"filename": "cover.png",
"alt": "Experimental eyewear forming in the midst of a post-apocolyptic scene"
}
]
},`It's like this
but a series of these in one array
Right now, if I go to the /projects/ page
it will load my navigation right away, but the component that handles all of this data is basically stuck until it all loads
including the videos and images
idk why it doesnt just show the text right away
and then everything jumps in at once when the videos and images are fully loaded which isn't what I want.
Vespid wasp
theres probably some non next.js concepts you want to consider
you can detect if an element is in the viewport
Channel catfishOP
what do you recommend?
like intersection observer?
Vespid wasp
yes
exactly
Channel catfishOP
I have a state called activeSection which is basically an index value detecting when the user is on each section
I guess I can conditionally load it in?
Vespid wasp
do you have any behavior preventing the videos from loading right away?
Channel catfishOP
like if user is on index 1, render in data from data.content[1]
I have autoplay enabled when the user hits that slide
Vespid wasp
that or just make sure you're keeping control of the state of each element correctly
Channel catfishOP
but no nothing to stop it
`
useEffect(() => {
// If the section we are on has a video, play it.
const videoSection = document.getElementById(activeSection);
const videoElement = videoSection?.querySelector("video");
if (videoElement) {
videoElement
.play()
.then(() => {
console.log("Video is auto-playing.");
})
.catch((error) => {
console.log(error);
});
}
}, [activeSection]);`Vespid wasp
sounds like you should disable autoplay for everything
Channel catfishOP
yeah maybe i disable it..
Vespid wasp
for sure
and then manually play it using your intersection observer
Channel catfishOP
I just did it right now
i throttled it to 3g wifi
still doesnt show anything until everything is loaded
Vespid wasp
everything as in every video?
or the json file?
Channel catfishOP
im actually not sure, im not pro at diagnosing the network tab maybe i can send u screenshot to find out
but its like ... everything
the video im assuming
since thats the biggest item
the text, images, and videos all pop in at once
Vespid wasp
one thing it has to do for sure is load your json so it knows what data to render
if its waiting for every image and video to also load before anything renders, that puzzles me a bit
Channel catfishOP
hopefully you can see that
Vespid wasp
what happens if you comment out your video and image components
does it load and show the title any faster?
Channel catfishOP
let me try that real quick
it doesnt
ok now this is making me think my json data is loading in slow or something
Vespid wasp
if that doesnt lead anywhere, I would need to see a hard refresh and screenshot of the network tab
well you should be able to see that in the waterfall there
@Vespid wasp if that doesnt lead anywhere, I would need to see a hard refresh and screenshot of the network tab
Channel catfishOP
the recent one is hard refresh
all of my screenshots are
i disable cache
Vespid wasp
i dont see your json loading there
Channel catfishOP
this is it again
theres no json
Vespid wasp
a lot of the assets appear to say they are loading from memory cache
oh, im probably fundamentally misunderstanding omething here
Channel catfishOP
is it because im importing my json as a hard import
and not fetch
Vespid wasp
right
Channel catfishOP
fuck
Vespid wasp
ok
Channel catfishOP
const project = data.find((project) => project.url === projectUrl);
Vespid wasp
i dont think the answer is to necessarily change it to fetch
Channel catfishOP
import data from "data.json";
this is how im using it rn
import json, then find the project
what do you suggest?
Vespid wasp
hang on let me look at your original code again to see what you're trying to do
is this hosted somewhere?
Channel catfishOP
GitHub
Vercel
Vespid wasp
i mean running
Channel catfishOP
Oh nah
Local env
do you want me to make it live
Vespid wasp
does discord have screenshare?
Channel catfishOP
Yea
Vespid wasp
I'm bored, maybe I could learn something myself by looking at it with you
Channel catfishOP
I gotta to bed
I graduate tomorrow lmao
Vespid wasp
oh nice
Channel catfishOP
I can paste the code
What do you want to see
It’s basically importing data in from a json
Feeding it to a child component as a prop
Vespid wasp
that makes sense
Channel catfishOP
Rendering it in by mapping over the data
Very simple setup
Vespid wasp
i guess i just want to see the bug
its blank for a while and then it all renders at once?
Channel catfishOP
Yea
I can record a vid
Vespid wasp
maybe also view source
Channel catfishOP
Vespid wasp
see if its doing some crazy dom updates
i see
so its not even rendering body until whatever that big file its loading is
Channel catfishOP
yeah
Idk what it is
I’ll check it out another day hope someone else can help
Thanks anyways
Vespid wasp
tbh i think what you're seeing is expected
the "big file" is main-app.js
so of course none of the js is going to be executed until that's finished loading