Giter VIP home page Giter VIP logo

blog-swr-demo's Introduction

We can easily create Client rendered pages (CSR) and Static generated pages (SG) using Next.js. But, often times, you'll want your page to use a combination of those different rendering methods. Like, you want your static page to be generated with some data from api, then once the users browser has hydrated the static page, you want CSR to kick in. There is one way we can use this, by using the excellent SWR plugin from Vercel (`creators of Next.js). Let's have a quick look about it in this article.

First, let's create a next app by running

npx create-next-app blog-swr-demo -y

Now we need to create a mock api to serve us articles/posts. Let's create a new file in pages/posts.js and paste in

export default (req, res) => {
    res.status(200).json({ 
        posts: [
            {title: "A", content: "asdf"},
            {title: "B", content: "qwert"},
            {title: "C", content: "zxcv"},
            {title: "D", content: "mnopq"},
            {title: "E", content: "aeiou"}
        ]
    })
  }

Now, we'll install the SWR plugin

npm i swr

And create our blog component and also import the useSWR hook from the plugin we just installed

import useSWR from "swr"


export default function Blog() {
  return (
    <div>
        Demo blog
        {
            posts.map((post) =>
                <h4>{post.title}</h4>
                <p>{post.content}</p>
            )
        }
    </div>
  )
}

Now, let's render the blog posts using the useSWR hook

import useSWR from "swr"

async function fetcherFunc(url) {
    const res = await fetch(url);
    return res.json();
}

export default function Blog() {
  const url = "http://localhost:3000/api/posts";
  const {data, error} = useSWR(url, fetcherFunc);
  if (!data) return <div>fetching</div>
  
  const {posts} = data;

  return (
    <div>
        Demo blog
        {
            posts.map((post) =>
                <div>
                    <h4>Article: {post.title}</h4>
                    <p>{post.content}</p>
                    <br/>
                </div>
            )
        }
    </div>
  )
}

Now let's create the static generated file for our page, for this we'll modify our code like

export default function Blog(props) {   // <<<<<<< changed here
//   const url = "http://localhost:3000/api/posts";
//   const {data, error} = useSWR(url, fetcherFunc);
//   if (!data) return <div>fetching</div>

  const {posts} = props; // <<<<<<<< Also here

  return (
    <div>
        Demo blog
        {
            posts.map((post) =>
                <div>
                    <h4>Article: {post.title}</h4>
                    <p>{post.content}</p>
                    <br/>
                </div>
            )
        }
    </div>
  )
}

export async function getStaticProps(context) {
    const res = fetch("http://localhost:3000/api/posts");
    const posts = await (await res).json()

    return {
        props: {
            posts
        }
    }
}

Let's generate the page. For that run

npm run build

You'll see this after it's successfully built

> [email protected] build
> next build

info  - Creating an optimized production build  
info  - Compiled successfully
info  - Collecting page data  
info  - Generating static pages (4/4)
info  - Finalizing page optimization  

Page                                                           Size     First Load JS
┌ ○ /                                                          3.46 kB        66.9 kB
├   └ css/c50ddf22b716c7b6b76d.css                             660 B
├   /_app                                                      0 B            63.4 kB
├ ○ /404                                                       3.46 kB        66.9 kB
├ λ /api/hello                                                 0 B            63.4 kB
├ λ /api/posts                                                 0 B            63.4 kB
└ ● /blog                                                      1.96 kB        65.4 kB
+ First Load JS shared by all                                  63.4 kB
  ├ chunks/e82d01500e11e0131e78851aa17fd9f5e63d6c88.ebefd9.js  2.47 kB
  ├ chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.519eb7.js  11.3 kB
  ├ chunks/framework.e2fe4a.js                                 41.8 kB
  ├ chunks/main.1a4cca.js                                      6.67 kB
  ├ chunks/pages/_app.6b4817.js                                531 B
  ├ chunks/webpack.50bee0.js                                   751 B
  └ css/6e9ef204d6fd7ac61493.css                               194 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
   (ISR)     incremental static regeneration (uses revalidate in getStaticProps)

Note, the if we keep adding posts to our mock api while our blog is running, the data doesn't get refreshed. We need to reload the page to do that

Let's fix that now. For that, we will pass the revalidateOnMount option in our useSWR hook So, the final code will be

import useSWR from "swr"

async function fetcherFunc(url) {
    const res = await fetch(url);
    return res.json();
}

export default function Blog(props) {
  const url = "http://localhost:3000/api/posts";
  const {data, error} = useSWR(url, fetcherFunc, {initialData: props, revalidateOnMount: true });

  const {posts} = data;
  if (!posts) return <div>fetching</div>

  return (
    <div>
        Demo blog
        {
            posts.map((post) =>
                <div>
                    <h4>Article: {post.title}</h4>
                    <p>{post.content}</p>
                    <br/>
                </div>
            )
        }
    </div>
  )
}

export async function getStaticProps(context) {
    const res = fetch("http://localhost:3000/api/posts");
    const {posts} = await (await res).json()

    return {
        props: {
            posts
        }
    }
}

Let's check

Source code

https://github.com/Salekin-1169/blog-swr-demo

Learning Material

The official docs (obviously)

{@embed: https://www.youtube.com/watch?v=eMwTEo6AjDc}

blog-swr-demo's People

Contributors

salekin-1169 avatar

Stargazers

adampweb avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.