Replace mock data with a real datasource:

Send HTTP request once the page has loaded - we would typically use useEffect() Runs whenever component is frist rendered, never after. Do: fetch your data inside it.

Manage state for the component - use useState() hook

const [loadedNotes, setLoadedNotes] = useState([]);

useEffect(()=> {
    //send http request and fetch data.
    //set on component
    setLoadedNotes(LOADED_NOTES);
}, []);

Full code (with function component):

function HomePage(){
    const [loadedNotes, setLoadedNotes] = useState([]);

    useEffect(()=> {
        //send http request and fetch data.
        //set on component
        setLoadedNotes(LOADED_NOTES);
    }, []);

    return <NoteList notes={LOADED_NOTES} />
}

export default HomePage;

useEffect() works like - whatever fn you pass into it - it executes that fn AFTER the function component is executed.

This means:

  1. First time the HomePage function component is executed, LOADED_NOTES will be an empty array.
  2. Then this useEffect will execute- update the state, due to which the component function will execute again (because state changed), and will render again.
  3. Therefore 2 render cycles.

Why emphasing on the 2 render cycle?

Because UX affected because (rerender/flickering) - and SEO affected - in the first render, data is not there! - because it is rendered in the second component execution cycle.

the prerendered HTML page (generated by nextjs automatically) does not wait for the second cycle - it always takes the result of the first render cycle and returns that as the pre rendered HTML code.

Thankfully nextjs has solution to this: Page Pre-rendering

Page pre rendering

Can use getStaticProps

  • reserved name
  • only works in pages/ (components under pages)
  • This executes before the component function is run
  • is allowed to be async. (ie you ca return promise) (nextjs will wait for the promise to get resolved)
  • You can use getSP to run code that woukd usualyy run on a server - like ccess file sytem, connect to a DB. Any code you write in here will never end up in client side, never execute on client side.

simply because this code is executed during the build process, not on the server and especially not on the clients of your visitors.

So the code in here will never reach the machines of your visitors.

It will never execute on their machines.

Now, here in getStaticProps, you can do whatever you want, for example, fetch data from an API or from a database or read data from some files in the file system.

But then once you’re done with whatever you did to get the data you need, you need to return an object here in getStaticProps.

You always need to return an object from gsp.

Now, in this object, you can configure various things but most importantly, you typically set a props property here and it has to be named props.

What props holds will be the props object you receive in your component function (HomePage(props)).

The structure of this props object is totally up to you, (we could have our notes key in there.) which holds our DUMMY_NOTES.

export async function getStaticProps(){
    //fetch data from an API
    return {
        props: {
            notes: DUMMY_NOTES
        }
    }
}

Therefore in our HomePage() we no longer need to manage state! We no longer need useEffect! - because we now get the data from props (thanks to gsp)

Final:

function HomePage(props){
    // const [loadedNotes, setLoadedNotes] = useState([]);

    // useEffect(()=> {
    //     //send http request and fetch data.
    //     //set on component
    //     setLoadedNotes(LOADED_NOTES);
    // }, []);

    return <NoteList notes={props.notes} />
}

export async function getStaticProps(){
    //fetch data from an API
    return {
        props: {
            notes: DUMMY_NOTES
        }
    }
}

export default HomePage;

We moved the data-fetching away from client (moved it to during the build process)