Bermain Search Params dengan nuqs di Next.js App Router

Bermain Search Params dengan nuqs di Next.js App Router

Zakiego

Zakiego

@zakiego

Abstrak

nuqs merupakan library search params state manager untuk Next.js.

Default behavior dari nuqs adalah client first, artinya, saat melakukan update search params, web tidak akan melakukan re-render. Ini hal yang bagus jika value dari search params hanya perlu dibaca melalui client side.

Namun, jika value perlu dibaca oleh server, maka tidak akan terbaca perubahannya. Untuk memicu re-render agar perubahan terbaca oleh server maka perlu ditambah opsi { shallow: false }.

Berbeda halnya dengan next-query-params yang mengusung server first, artinya setiap perubahan value akan langsung terbaca oleh server.

Rasakan perbedaan antara search params client side dan server side pada nuqs di nuqs-playground.vercel.app

Sedangkan untuk next-query-params bisa dicoba di seach-params-playground.vercel.app

Pendahuluan

Tulisan ini merupakan lanjutan dari tulisan Membuat Komponen Search di Next.js App Router. Jika sebelumnya kita menggunakan library next-query-params, untuk me-manage search params, kali ini kita akan bermain dengan nuqs.

Sebenarnya sebelum ini, saya sempat mencicipi nuqs. Namun karena keterbatasan pengetahuan, akhirnya saya tidak melanjutkannya.

Terima kasih untuk Mas @alfonsusac yang men-trigger saya untuk kembali membaca lebih dalam dokumentasi nuqs.

Selayang Pandang

nuqs mendefinisikan dirinya sebagai, "Type-safe search params state manager for Next.js".

Mari kita mulai. Tentu saja, framework yang digunakan dalam tulisan ini adalah Next.js.

Pertama, install nuqs.

pnpm add nuqs

Buat component file yang berisi <input/>, kemudian value onChange kita teruskan menjadi search params dengan useQueryState.

// src/app/client.tsx

'use client'
 
import { useQueryState } from 'nuqs'

export function Demo() {
  const [name, setName] = useQueryState("name");
  return (
    <>
      <input value={name || ""} onChange={(e) => setName(e.target.value)} />
      <p>Hello, {name}!</p>
    </>
  );
}

Mengan perlu menuliskan "use client" pada baris paling atas?

Karena, sejak diperkenalkannya paradigma App Router di Next.js, default dari setiap component adalah server component. Sedangkan, dalam kasus ini, kita memerlukan onChange dari <input/> yang merupakan client component. Sebab itu, perlu untuk menuliskan "use client" pada baris teratas, untuk memberi tahu React, bahwa ini merupakan client component (Client Components).

Terakhir, import component <Demo/> yang sudah kita buat ke /src/app/hello/page.tsx.

Hasilnya, setiap kali memasukkan value di <input/>, maka search params akan langsung ter-update.

Contohnya, dari example.com/hello akan berubah menjadi example.com/hello?name=zaki.

Untuk contoh lebih banyak, bisa dilihat di nuqs.47ng.com/playground.

Perbedaan nuqs dengan next-query-params

Sebelumnya, saya sempat menggunakan nuqs pada tweet ini. Perbedaan paling mencolok antara nuqs dan next-query-params adalah:

  • nuqs berjalan di atas client-first 
  • sedangkan, next-query-params adalah server-first

Apa bedanya?

Kamu bisa merasakan langsung perbedaan client-first (nuqs-playground.vercel.app/nuqs-client) dan server-first (nuqs-playground.vercel.app/nuqs-server)

Dengan nuqs mengusung client-first, maka, kita tidak bisa mengakses search params dari server side.

Misal, kita mengunjungi halaman example.com/hello.

Kemudian, saat mengetikkan input nama, URL berubah menjadi example.com/hello?name=zaki.

Meski URL berubah, namun karena nuqs adalah client first, maka value dari name yang kita ambil dari search params akan tetap kosong, jika menggunakan server side.

nuqs secara default tidak men-trigger pembaruan halaman ke server. Sehingga meski kita URL di browser kita berubah menjadi example.com/hello?name=zaki, sejatinya, server masih menganggap kita berada pada halaman example.com/hello saja.

interface Props {
  searchParams: {
    name?: string;
  };
}

export default async function Page(props: Props) {
  const { searchParams } = props;
  const { name } = searchParams;

  return (
    <div>
      value from server: {name}
    </div>
  );
}

Namun berbeda halnya pada client component, seperti pada <Demo/> tadi.

Izinkan saya meletakkan kodenya sekali lagi.

// src/app/client.tsx

'use client'
 
import { useQueryState } from 'nuqs'

export function Demo() {
  const [name, setName] = useQueryState("name");
  return (
    <>
      <input value={name || ""} onChange={(e) => setName(e.target.value)} />
      <p>Hello, {name}!</p>
    </>
  );
}

Di kode tersebut, value dari name akan langsung terbaca, meski kita tidak melakukan pembaruan halaman ke server.

Hal ini berkebalikan dengan next-query-params, setiap kali melakukan update value pada <input/>, maka ia akan memicu pembaruan halaman.

Alhasil, saat URL terupdate dari example.com/hello menjadi example.com/hello?name=zaki, server langsung mengenali bahwa kita sudah berada di URL example.com/hello?name=zaki.

nuqs namun Server Side

Setelah melakukan pembacaan lebih seksama, meski nuqs adalah client-first, kita tetap bisa menjalan re-render, yaitu dengan menambahkan { shallow: false }.

Docs nuqs.47ng.com/docs/options

useQueryState('foo', { shallow: false })

Dengan setting-an di atas, maka kita bisa mendapatkan search params melalui server side.

Kamu bisa mencobanya di sini nuqs-playground.vercel.app/nuqs-server.

Buah Tangan

Berikut beberapa reply dari author nuqs langsung:

Selain itu, nuqs juga ternyata digunakan oleh vercel.com 😅

Penutup

nuqs memiliki DX (developer experience) yang lebih mudah ketimbang next-query-params, karena tidak perlu menambahkan kode pada fitur layout.

Namun, karena nuqs adalah client-first, maka value dari search params, perubahan value tidak bisa didapat secara langsung pada server side, kecuali menggunakan { shallow: false }. Berbeda dengan next-query-params yang sedari awal adalah server-first, sehingga perubahan value langsung bisa dibaca oleh server.

Alhasil, semua kembali ke sisi developer. Pertanyaannya:

  1. Apakah kamu melakukan fetch pada server-side atau client side?
  2. Selanjutnya, apakah value search params perlu untuk bisa dibaca server? Karena pada beberapa kasus, search params tidak harus langsung bisa dibaca oleh server

Sekian dan terima kasih.


Selesai ditulis hari Kamis, 11 April 2024 pada 13:39, atau hari kedua lebaran.