Next js simple blog
Published: 2022-11-08 23:22:57

Membuat blog sederhana

> https://picsum.photos/ 
https://jsonplaceholder.typicode.com/
https://nextjs.org/docs/api-reference/next/image#remote-patterns
import styles from "../styles/Home.module.css"
import Image from "next/image"
import Link from "next/link"
import {useRouter} from "next/router"


```
pnpm create next-app myblog
typescript > No
eslint > No
```
kita pakai css bawaan 

![Image description 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oyn5a4k3ys7aa49r7f0.png)

![Image description 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eljgtq1yf33xhy9u9zhm.png)

```
//index.jsx

import styles from "../styles/Home.module.css"
export default function Home (){
  return (
    <main className={styles.main}>
      <h1>My Blog</h1>
    </main>
  )
}
```

![Image description3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dq5ofe2cfc40c45wh3a.png)

![Image description4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k111att39x7r9qjybndv.png)

selanjutnya kita akan melakukan fetching data,

```
import styles from "../styles/Home.module.css"

export default function Home ({data, page}){

  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : ctx.query.page || 1
    }
  }
} 
```

![Image description5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idp8m9c8y7d3j3kwun8m.png)

![Image description6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67m3y5ej8p8dpjx7z7mq.png)

```
//index.jsx

import styles from "../styles/Home.module.css"

export default function Home ({data, page}){

  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id}>
            <h3>{e.title}</h3>
            <p>{e.body}</p>
          </div>
        ))}
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : ctx.query.page || 1
    }
  }
} 
```

![Image description8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w56hma82a4ud4o34ly3e.png)

![Image description9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8g6ytt74yhdm0qrdnirw.png)

kita sudah berhasil menampilkan data jsonnya sekarang kita akan menampilkan gambarnya dari picsum.photos

![Image description11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/br1fbj4urfd7qlmxlc8u.png)

![Image description12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ccduqoy4d8mnbwsoqho.png)

```
//index.jsx

import styles from "../styles/Home.module.css"

export default function Home ({data, page}){

  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id}>

            <img src={ `https://picsum.photos/seed/${e.id}/500/300` } alt={e.title} />
            <h3>{e.id} . {e.title}</h3>
            <p>{e.body}</p>
          </div>
        ))}
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : ctx.query.page || 1
    }
  }
} 
```

---

selanjutnya kita akan menampilkan gambar dengan images next js



![Image description next image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r23lagtki13bvegqyaqk.png)

![next image config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6qqvybyuqxv1a8lzn2j.png)

```
//next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  images  : {
    remotePatterns : [
      {
        protocol : 'https',
        hostname : 'picsum.photos'
      }
    ]
  }
}

module.exports = nextConfig

```

![error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydl9tgox3pcgay5wgg97.png)

```
import styles from "../styles/Home.module.css"
import Image from "next/image"


export default function Home ({data, page}){

  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id} className={styles.blogCard}>

            <Image 
            src={ `https://picsum.photos/seed/${e.id}/200/200` } 
            alt={e.title} 
            width={200}
            height={200}
            />

            <h3>{e.id} . {e.title}</h3>
            <p>{e.body}</p>
          </div>
        ))}
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : ctx.query.page || 1
    }
  }
} 
```
akan ada pesan error karena kita mengganti config js, jadi servernya kita matikan dulu, kemudian start ulang.

![tampil berhasil](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddhijxzfrhbh7kncjz66.png)

selanjutnya kita akan menampilkan prev dan next dibagian bawah page kita 

```
//index.jsx

import styles from "../styles/Home.module.css"
import Image from "next/image"
import {useRouter} from "next/router"

export default function Home ({data, page}){

  const router = useRouter()

  //function untuk pagination
  const nextPage = ()=>{
    router.push(`/?page=${page + 1}`)
  }

  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id} className={styles.blogCard}>

            <Image 
            src={ `https://picsum.photos/seed/${e.id}/200/200` } 
            alt={e.title} 
            width={200}
            height={200}
            />

            <h3>{e.id} . {e.title}</h3>
            <p>{e.body}</p>
          </div>
        ))}
      </div>

      <div className={styles.btnPagination}>
        <button>prev</button>
        <button onClick={nextPage}>next</button>
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : parseInt(ctx.query.page) || 1
    }
  }
} 
```

![next page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggye52f6flwo0mwezrko.png)

sekarang kita ke function prev page

```
import styles from "../styles/Home.module.css"
import Image from "next/image"
import {useRouter} from "next/router"

export default function Home ({data, page}){

  const router = useRouter()

  //function untuk pagination
  const nextPage = ()=>{
    router.push(`/?page=${page + 1}`)
  }

  const prevPage =()=>{
    if (page==1){
      return
    }
    router.push(`/?page=${page - 1}`)
  }



  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id} className={styles.blogCard}>

            <Image 
            src={ `https://picsum.photos/seed/${e.id}/200/200` } 
            alt={e.title} 
            width={200}
            height={200}
            />

            <h3>{e.id} . {e.title}</h3>
            <p>{e.body}</p>
          </div>
        ))}
      </div>

      <div className={styles.btnPagination}>
        <button onClick={prevPage}>prev</button>
        <button onClick={nextPage}>next</button>
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : parseInt(ctx.query.page) || 1
    }
  }
} 
```
selanjutnya kita akan buat Link tag a yang akan mengarahkan detailnya, sebelumnya buat folder detail dan files [id].jsx

```
//detail > [id.jsx]

import styles from "../../styles/Home.module.css"
import Image from "next/image"
import { useRouter } from "next/router"


export default function Details ({data}){
    const router = useRouter()

    return (
        <main className={styles.main}>
            <h1>{data.title}</h1>
            <Image 
                src={`https://picsum.photos/seed/${data.id}/900/500`}
                width={900}
                height ={500}
                alt ={data.title}
             />

            <p>{data.body}</p>
            <button onClick={()=>{router.back()}}>back</button>
        </main>
    )
}

export async function getServerSideProps(ctx){
    const result =await fetch("https://jsonplaceholder.typicode.com/posts/" + ctx.params.id)
    const data = await result.json()

    return {
        props : {
            data : data
        }
    }
}
```
tambahkan Link

```
//index.jsx

import styles from "../styles/Home.module.css"
import Image from "next/image"
import Link from "next/link"
import {useRouter} from "next/router"

export default function Home ({data, page}){

  const router = useRouter()

  //function untuk pagination
  const nextPage = ()=>{
    router.push(`/?page=${page + 1}`)
  }

  const prevPage =()=>{
    if (page==1){
      return
    }
    router.push(`/?page=${page - 1}`)
  }



  return (
    <main className={styles.main}>
      <h1>My Blog {page}</h1>

      <div className="styles.cardWrapper">

        {data.map((e)=>(
          <div key={e.id} className={styles.blogCard}>

            <Image 
            src={ `https://picsum.photos/seed/${e.id}/200/200` } 
            alt={e.title} 
            width={200}
            height={200}
            />

            <h3>{e.id} . {e.title}</h3>
            <p>{e.body}</p>

            <Link href={`/details/${e.id}`}>Detail</Link>
          </div>
        ))}
      </div>

      <div className={styles.btnPagination}>
        <button onClick={prevPage}>prev</button>
        <button onClick={nextPage}>next</button>
      </div>

    </main>
  )
}

export async function getServerSideProps(ctx){

  console.info(ctx)
  const result = await fetch("https://jsonplaceholder.typicode.com/posts?_page=" + ctx.query.page)
  const data = await result.json()

  return {
    props : {
      data: data,
      page : parseInt(ctx.query.page) || 1
    }
  }
} 
```

![Myblog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lntjzuov28g5qtlr328.gif)


![halaman 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6loabygoexbz3dkowtw.png)

![Details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2nk6qclekf1gpz5ovo56.png)

selanjutnya kita akan menambahkan css 

```
//Home.module.css

.main {
  min-height: 100vh;
  padding: 4rem 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  max-width: 900px;
  margin: 0 auto;
}

.cardWrapper {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.blogCard {
  display: flex;
  gap: 20px;
  padding: 20px;
  border: 1px dashed whitesmoke;
}
```

![blog4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iiqdsttye749wqaou17t.png)

![Details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xgwbwe654nm281l7npv.png)

https://github.com/andiks2018/JvalleyNext-simpleblog.git