Skip to content

Label yang Bisa Bohong: Saat Vocab Status Hidup di Dua Tempat

Adityo Guni Waluyo

Satu lib jadi rumah label enam status; nilai tak dikenal tampil jujur sebagai teks mentah dengan gaya netral, bukan label salah.

Ringkasan

Gue liat status di halaman publik cuma jadi teks polos gara-gara kamusnya masih versi lama 4 status padahal backend udah 6. Akhirnya kamus dipusatin di lib layanan-flow biar jadi satu sumber kebenaran dan dijaga TypeScript biar nggak ketinggalan. Kalau ada status asing tinggal fallback netral jadi tetap jujur nggak ngarang label.

Saya cek halaman status publik KotaPortal sore itu, dan ada tiket yang labelnya cuma teks polos: disetujui. Warna netral, tanpa ikon, tanpa kelakapan. Padahal di dashboard admin, status yang sama tampil sebagai badge hijau yang rapi. Dugaan pertama saya, komponen badge-nya yang rusak. Ternyata bukan. Halaman publik memang belum pernah mengenal status itu, karena dia masih menyimpan kamus label sendiri yang usang.

Kamus itulah masalahnya. Halaman status punya konstanta STATUS_MAP duplikat berisi empat status lama dari zaman pending-reviewed-approved-rejected. Sementara lib layanan-flow di tempat lain sudah lama menjaga enam status, warisan mesin transisi di backend yang menolak loncat status. Backend tinggal mengirim enam status itu, dan dua di antaranya nggak ada di kamus duplikat halaman publik. Hasilnya bukan error merah; yang muncul teks mentah tanpa label. Dan ini bukan satu titik: daftar tiket dan kartu hasil pencarian tiket di halaman yang sama sama-sama membaca kamus kembar itu, jadi salah tampilnya dobel. Nyatanya, map lama itu nggak pernah mengenali satu pun dari enam status baru, jadi semua tiket yang statusnya bukan empat nilai lama pasti jatuh ke teks mentah. Artinya percikan aneh yang saya lihat itu bukan kasus istimewa, melainkan kondisi normal halaman itu selama kamus kembarnya dibiarkan basi.

Masalahnya Bukan Warna, Tapi Kamus Kembar

Mengganti empat entri jadi enam bukan solusi, karena lusa bisa jadi tujuh lagi. Kepemilikan label saya pindahin ke satu tempat: STATUS_LABEL di lib layanan-flow yang jadi mirror peta transisi. Halaman publik tinggal memanggil, nggak menyimpan kamus sendiri. Ini prinsip yang ditulis rapi di panduan Redux: simpan data seminimal mungkin, sisanya derive dari sumber kebenarannya [7]. Kamus yang diduplikasi di dua komponen itu resep drift; cukup satu yang benar, yang lain jangan ditiru.

Sisi tipenya juga ikut dikunci. Record untuk warna badge sifatnya exhaustif: begitu ada status baru masuk union, TypeScript langsung komplain kalau ada yang kelewat [3]. Union type sendiri cuma gabungan beberapa tipe yang nilainya boleh salah satu dari tipe-tipe itu [8], jadi kompiler tahu persis daftar lengkapnya. Kelemahan strategi ini satu dan perlu jujur diakui: tipe hidup di waktu kompilasi. Begitu jadi JavaScript, jaga-jaga runtime tetap wajib ada.

Fallback yang Jujur dan Angka yang Dijaga

Guard isLayananStatus menutup celah runtime tadi. Nilai dikenal? Pakai label dan warna dari lib. Nilai asing? String mentah ditampilkan dengan warna netral. Nggak ada tebakan label dari status lain yang mirip, dan pengguna tetap bisa membaca nilai aslinya. Warga yang kebetulan membuka tiketnya di tengah migrasi pun nggak perlu tahu apa-apa; yang dia lihat konsisten, entah label resmi atau nilai mentah yang jujur. Untuk kasus nilai null atau undefined, operator ?? mengambil operan kanan hanya kalau kirinya nullish [12], jadi fallback berjalan mulus tanpa if bertele-tele. Gagalnya terkendali dan jujur, bukan salah tampil.

Satu perubahan kecil yang dulu suka saya remehkan: countKey di STATUS_TABS admin jadi wajib. Sebelumnya properti itu opsional, konsekuensinya tab baru bisa lahir tanpa angka dan baru ketahuan pas ada yang lihat dashboard. Sekarang build gagal lebih dulu. Penjaganya kompiler, bukan ketelitian manusia, dan biayanya nol karena tipe statis memang nggak ikut ke runtime [3]. Buat daftar tiket, properti key [10] tetap dipasang supaya React bisa melacak item mana yang berubah saat daftar disegarkan, dan penanda data-testid lama nggak ada yang digeser. Refactor sebesar apa pun, jalur pengujian otomatis harus tetap hidup.

Saya milih tampil polos tapi benar daripada berwarna tapi bohong. Kamus label sekarang cuma satu, kompiler yang jaga kelengkapannya, dan kalau nanti vocabulary berubah lagi, halaman publik tinggal nuronin. Kalau nanti status ketujuh lahir, yang perlu diubah cuma union dan satu Record di lib; halaman publik nggak perlu disentuh sama sekali karena dia nggak menyimpan kamus apa pun. Itu definisi refaktor yang selesai: bukan cuma masalah hari ini yang hilang, tapi jenis masalah yang sama nggak bisa lahir lagi di tempat lain. Nggak ada kamus kedua yang harus saya kejar keteteran.

Sumber

Artikel terkait