2019-11-20

Dynamic data fetching in Next.js

next, ssr, react, javascript, devjournal

banner

Image by Gerd Altmann from Pixabay

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.

1const Index = ({ posts, users }) => (2  <>3    <section>4      <h1>Posts</h1>5      <ul>6        {posts.map(post => (...))}7      </ul>8    </section>9    <section>10      <h1>Users</h1>11      <ul>12        {users.map(user => (...))}13      </ul>14    </section>15  </>16)17
18Index.getInitialProps = async function() {19  const postsResponse = await fetch(postsUrl)20  const posts = (await postsResponse.json()).slice(0, 5)21
22  const usersResponse = await fetch(usersUrl)23  const users = (await usersResponse.json()).slice(0, 5)24
25  return { posts, users }26}

https://codesandbox.io/s/nextjs-fetch-jsonplaceholder-posts-u4qq3?fontsize=14&hidenavigation=1&module=%2Fpages%2Findex.js&theme=dark

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).

1const Users = ({ users }) => (2  <section>3    <h1>Users</h1>4    <ul>5      {users.map(user => (...))}6    </ul>7  </section>8);9
10const getUsers = url => fetch(url).then(_ => _.json());11
12const Index = ({ posts }) => {13  const [shouldFetchUsers, setShouldFetchUsers] = useState(false);14
15  const { data: users } = useSWR(16    () => (shouldFetchUsers ? usersUrl : null),17    getUsers18  );19
20  return (21    <>22      <section>23        <button onClick={() => setShouldFetchUsers(true)}>Users?</button>24        <h1>Posts</h1>25        <ul>26          {posts.map(post => (...))}27        </ul>28      </section>29      {users && <Users users={users} />}30    </>31  );32};33
34Index.getInitialProps = async function() {35  const postsResponse = await fetch(postsUrl);36  const posts = (await postsResponse.json()).slice(0, 5);37  return { posts };38};

https://codesandbox.io/s/nextjs-fetch-jsonplaceholder-posts-dynamic-users-hr34q?fontsize=14&hidenavigation=1&module=%2Fpages%2Findex.js&theme=dark

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