← Go Back

Dynamic data fetching in Next.js

Broken Post?Let me know

After going thru the wonderful Next.js tutorial, I decided to write a simple data fetching site from scratch.

It was tougher than I expected.

TIL that you can fetch data from getInitialProps to return a shell, and also let the rest of the page "dynamic" using fetch.


Server-side data fetch with "getInitialProps"

Here, I am getting both posts and users from getInitialProps in index.js page.

const Index = ({ posts, users }) => (
  <>
    <section>
      <h1>Posts</h1>
      <ul>
        {posts.map(post => (...))}
      </ul>
    </section>
    <section>
      <h1>Users</h1>
      <ul>
        {users.map(user => (...))}
      </ul>
    </section>
  </>
)

Index.getInitialProps = async function() {
  const postsResponse = await fetch(postsUrl)
  const posts = (await postsResponse.json()).slice(0, 5)

  const usersResponse = await fetch(usersUrl)
  const users = (await usersResponse.json()).slice(0, 5)

  return { posts, users }
}

infographics

Credit: Refer to ups/downs on Rendering on the Web

Client-side data fetch (with "SWR")

Second experiment was to fetch users dynamically on button click.
I was skeptical that it'd work as HTML is generated on the server.

But I was able to get users data on the client-side no problem.

You can see that I am fetching only posts via getInitialProps but users data is fetched using useSWR(, which is a convinience method to fetch remote data from Zeit to w/o useEffect boilerplate code).

const Users = ({ users }) => (
  <section>
    <h1>Users</h1>
    <ul>
      {users.map(user => (...))}
    </ul>
  </section>
);

const getUsers = url => fetch(url).then(_ => _.json());

const Index = ({ posts }) => {
  const [shouldFetchUsers, setShouldFetchUsers] = useState(false);

  const { data: users } = useSWR(
    () => (shouldFetchUsers ? usersUrl : null),
    getUsers
  );

  return (
    <>
      <section>
        <button onClick={() => setShouldFetchUsers(true)}>Users?</button>
        <h1>Posts</h1>
        <ul>
          {posts.map(post => (...))}
        </ul>
      </section>
      {users && <Users users={users} />}
    </>
  );
};

Index.getInitialProps = async function() {
  const postsResponse = await fetch(postsUrl);
  const posts = (await postsResponse.json()).slice(0, 5);
  return { posts };
};

Unrelated but just a thought.

I just ran across "App Shell model", for which Next.js can be used to provdie the "shell" and do dynamic data fetching after the load.

https://developers.google.com/web/fundamentals/architecture/app-shell


Image by Gerd Altmann from Pixabay