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
//index.jsx import styles from "../styles/Home.module.css" export default function Home (){ return ( <main className={styles.main}> <h1>My Blog</h1> </main> ) }
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 } } }
//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 } } }
kita sudah berhasil menampilkan data jsonnya sekarang kita akan menampilkan gambarnya dari picsum.photos
//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
//next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, images : { remotePatterns : [ { protocol : 'https', hostname : 'picsum.photos' } ] } } module.exports = nextConfig
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.
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 } } }
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 } } }
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; }
Top comments (0)