Kode Terlalu Repetitif di Reducer? Introduce: Higher-Order Reducer

Jihad Dzikri Waspada
codewey
Published in
4 min readApr 21, 2018
Simple Photograph (source)

Salaam semuanya! Maaf udah lama ndak nulis lagi, diitung-itung udah 9 bulan vakuum. Entah kenapa semenjak nikah, rutinitas-rutinitas kayak nulis dan belajar-belajar jadi suka terbengkalai πŸ˜› You know lah wkwk. Sampai akhirnya disentil sama Shifu Irfan Maulana buat nulis lagi 😁 *maafkan saya Shifu

So, balik ke topik. Higher-Order Reducer. Entah istilah ini tepat atau nggak, saya sendiri kurang begitu yakin, tapi saya akan coba terangkan secara singkat dimulai dari permasalahan yang sangat sangat simple: Async Actions.

The problem

Biasanya, Async Actions ini direpresentasikan dengan tambahan 3 suffix berikut: REQUEST, SUCCESS, dan FAILED.

const createAction = actionName => payload => ({
type: actionName,
payload
})
const getUserRequest = createAction('GET_USER_REQUEST')
const getUserSuccess = createAction('GET_USER_SUCCESS')
const getUserFailed = createAction('GET_USER_FAILED')

Setelah berhasil mendapatkan datanya dari suatu endpoint, kita hanya ingin menyimpan datanya di redux store. Urusan pengolahan business logic bisa kita serahkan ke function lain (use reselect), saat ini kita hanya fokus pada penyimpanan datanya saja.

Kita bisa handle ketiga action creators ini di reducer seperti:

Sangat standar. Works good. Nothing special.

Muka Standar

BUT. Bagimana jadinya kalo Async Action kita lebih dari satu? Bagaimana kalau kita ingin fetch post juga? Solusi paling mudah: tinggal kopas aja dari user dan ganti key-nya jadi post 😎

Hmm, ada yang salah? Keliatannya sih baik-baik aja, tapi agak kurang sreg gimanaa gitu ya. I smell repetitive code, yang mungkin saja OK, tapi in most cases not OK. Karena bisa jadi, kita gak cuma akan fetch user dan post saja, mungkin kita juga mau fetch data-data lain dan menyimpan hasilnya di redux store. Jika hal itu dilakukan dengan metode copy-paste-modify seperti halnya di atas, konsekuensinya adalah longer repetitive code, WICIS gak baik.

(sengaja saya bold, biar keliatan pinter bahasa inggris 😌)

Less code === Less bug

Jadi, bagaimana solusinya?

Higher-Order Reducer

Sesuai namanya, Higher-Order Reducer adalah suatu reducer yang menerima dan/atau mengembalikan reducer lain. Singkat cerita, kita akan meng-extract bagian yang repetitif tersebut menjadi sebuah reducer. Reducer di dalam reducer. Sebagai glue-nya, kita bisa menggunakan combineReducer dari redux.

Tapi sebelum masuk ke bagian intinya, saya ingin sedikit mengubah fungsi createAction dan menambahkan sebuah fungsi baru bernama createAsyncAction agar solusi yang ditawarkan menjadi lebih menarik.

Async Action Creators

(Yha, function adalah sebuah Object di Javascript. Bisa dicoba dengan menjalankan function seperti layaknya mengakses sebuah object seperti: document.addEventListener.length. Lihat apa yang akan terjadi, nomor 7 bikin kamu geleng-geleng kepala!)

Daaan sekarang ke intinya, setting up the reducer:

combineReducers sebagai glue reducers kita

Perbedaan mendasar dari HOR ini adalah, kita membuat satu reducer sendiri untuk masing-masing object (dalam hal ini user dan post). Dibandingkan solusi awal yang hanya mengambalikan 1 reducer (untuk 2 object), dengan solusi HOR ini kita mengembalikan 2 reducer sekaligus (1 reducer untuk 1 object).

Jika dianalogikan, struktur redux store pada solusi awal adalah

// redux store solusi awal
(state, action) => ({
user: { // <- PLAIN OBJECT
data: {}
asyncState: ...,
},
post: { // <- PLAIN OBJECT
data: {}
asyncState: ...,
},
...
})

Bandingkan dengan menggunakan HOR:

// redux store solusi HOR
(state, action) => ({
user: (ownState, action) => ({ // <- REDUCER
data: {}
asyncState: ...,
}),
post: (ownState, action) => ({ // <- REDUCER
data: {}
asyncState: ...,
}),
...
})

Yha, sangat sangat sederhana. Tapi terkadang untuk menciptakan sesuatu yang sederhana itu tidak mudah. Senada dengan ucapan Legenda Sepak Bola Barcelona, Johan Cruyff ketika mencetus taktik sepakbola tiki-taka:

Playing football is very simple, but playing simple football is the hardest thing there is β€” Johan Cruyff

atau Legenda Sinetron Kolosal Indosari ketika terbang dengan naga:

Coding is very simple, but finding simple solution with code is the hardest thing there is β€” Jihad D. Waspada

Penutup

Dengan memanfaatkan konsep Higher-Order Reducer, kita bisa mengeliminasi kode yang repetitif di reducer sembari tetap menjaga struktur redux store kita. Potensi kegunaan HOR ini sangat luas, bisa diterapkan di kasus-kasus yang lain. Saya pribadi menggunakan konsep HOR ini untuk pekerjaan yang berhubungan dengan Form.

Oh ya, createAsyncCreator di atas, saya derive dari Project Typescript-FSA. Sangat merekomendasikan library ini karena Typescript nya maknyus. Integrasi ke berbagai side-effect library-nya juga cukup memadai. Bisa ke Saga, ke Observable, atau bahkan ke reducer itu sendiri. Cek aja ya πŸ˜‰

Terkahir, semoga tulisan ini bisa bermanfaat. Dan doakan juga semoga saya bisa konsisten nulis di medium lagi πŸ˜„. Dan semoga yang jomblo segera dapet istri! Bye!

--

--

Jihad Dzikri Waspada
codewey
Editor for

Software Developer @Chordify, Utrecht. NOTE: Please navigate to https://jihadwaspada.com. I no longer write on Medium