Kenalan dengan Vuex, State Management di Vue Js

  bcscoder
30 Dec 2017 at 11:11 pm

Halo teman ngide! Kali ini kita akan melanjukan belajar tentang vuejs, lebih tepatnya tentang bagaimana mengatur state di dalam aplikasi vue js yang kita punya.

Kalau di React mereka punya Redux, di VueJS, mereka punya yang namanya Vuex.

Lalu kenapa kita harus menggunakan Vuex untuk state management?

Kemudahan utama kenapa kita harus menggunakan Vuex sebagai centralized state management adalah mempermudah mengakses state atau data di beberapa component sekaligus.

Catatan

Penggunaan state management tidak selalu harus dilakukan. Jadi jika data yang diperlukan hanya sedikit dan bisa di hadle dengan data flow yang standar seperti menggunakan props atau emit event maka itu udah cukup. Tapi jika casenya kalian butuh mengakses data yang banyak dan bisa di reuse di component lain maka Vuex menjadi pilihan yang tepat. 

Apa itu Vuex?

Saya kutip dari dokumentasi official, Vuex adalah sebuah state management pattern dan library untuk aplikasi VueJS.  Vuex bertugas sebagai centralized store untuk semua component yang di dalam aplikasi kamu, yang memastikan bahwa state hanya bisa di rubah dengan cara yang pasti.

Konsep Utama Vuex

Jadi sebelum langsung ngoding, ada baiknya kita mengenal beberapa konsep dasar yang ada di dalam Vuex. Pusat dari Vuex adalah sebuah "store" yang akan berfungsi sebagai kontainer dari semua state yang ada di dalem aplikasi kamu. Di dalam store memilki beberapa bagian-bagian yang dengan fungsinya masing-masing yaitu:

1. State

State adalah sebuah object dimana tempat semua data aplikasi berada. Contohnya kurang lebih seperti ini:

const store = new Vuex.Store({
  state: {
    count: 1,
    color: 'red'
  }
})

Jadi state ini saya bilangnya sebuah json yang berisi data-data yang akan kita akses dari component yang ada.

Untuk cara mengaksesnya state langsung seperti contoh di atas dengan menggunakan store.state.count atau store.state.color. Atau menggunakan global vuex  tanpa harus di import di setiap component dengan this.$store.state.count .

2. Getter

Sesuai namanya, Getter berfungsi untuk mengakses state.

Lalu apa bedanya mengakses state secara langsung dan melalu Getter?

Dengan menggunakan Getter kita bisa mengolah terlebih dahulu state yang akan kita ambil seperti fungsi computed yang ada di VueJS. Jadi kita bisa memfilter data state sebelum di panggil. 

Contohnya:

getters: {
		doneTodos(state){

			return state.todos.filter(function(item){
				return item.done == true
			})

		},
		pendingTodos(state){

			return state.todos.filter(function(item){
				return item.done == false
			})

		},
	},

3. Mutation

Mutation adalah satu-satunya cara untuk merubah state. Jadi mutation ini bisa dibilang mirip event yang ada di dalam store. Mutation terdiiri dari sebuah string nama dan handlernya. 

Contohnya gini:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  }
})

Nah di atas kita punya sebuah mutations dengan type name increment yang memilki handler dimana jika dipanggil akan menambah nilai dari state count sebanyak 1. 

Lalu cara memanggillnya di dalam component adalah dengan this.$store.commit('nama mutation').

4. Action

Apa lagi nih action? Action mirip dengan mutation, bedanya adalah mutation hanya bisa di akses secara synchronous sedangankan action bisa di akses secara asynchronous. 

Tidak tahu apa bedanya synchronous dengan assynchronous? Google haha.

Nah action ini tidak merubah state, tapi action akan memanggil mutation dan mutation yang akan merubah state.

Kita butuh action ketika melakukan proses asynchronous dan perlu untuk merubah state. Misalnya saat selesai melakukan request ajax. Cara memanggil state di component atau biasa dibilang dispatch adalah dengan this.$store.dispatch('nama action')

5. Modules

Seperti yang kita bahas soal state sebagai sebuah single tree json dan harus menampung semua state disana. Maka saat kita punya banyak sekali state yang harus di handle maka datanya akan membengkak dan susah untuk di maintenance.

Solusinya adalah dengan menggunakan modules.

Jadi store yang tadi besar itu kita bisa pecah-pecah lagi menjadi module yang lebih kecil. Menariknya masing-masing module ini selain berisi state, juga bisa berisi mutation, getter, dan action sendiri.

Kita lihat saja contohnya di bawah ini:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state

Nah kita sudah belajar sedikit konsep dasar seperti apa sih Vuex itu.

Selanjutnya kita coba implementasikan Vuex ke dalam aplikasi VueJS yang sudah pernah kita buat sebelumnya yaitu tentang bagaimana cara membuat todolist, kalian bisa baca disini: Mebuat Todolist Dengan VueJS. Kalian wajib mengikuti tutorial sebelumnya karena code yang di pakai adalah code todolist app sebelumnya.

Include Vuex

Buka file index.html dan tambahkan script vuex ini di bawah script vuejs.

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>

Membuat Store

Buka file app.js, kita akan membuat Vuex store.

tambahkan const store seperti di bawah ini sebelum pemanggilan VueJS. Lalu tambahkan const store  itu ke dalam pemanggilan VueJS.

const store = new Vuex.Store({
	state: {
		
	},
	mutations: {
	    
	  },
	getters: {
		
	},
})

var app = new Vue({
	el: '#app',
	store,
	data: {
		'message': 'Hello world'
	},
});

Sekarang kita coba buka di browser, disini saya memakai Chrome dan buka developer console dan di tab Vue, kamu bisa mengecek apakah Vuex sudah terinstall dengan baik di aplikasi yang kita buat

Memindahkan data todos ke dalam State

Sekarang saatnya memindahkan data todos yang sebelumnya ada di dalam component ke dalam state di "store"

Pindahkan seperti di bawah ini:

state: {
		todos: [
		{
			name: 'Todo 1',
			done: false,
		},
		{
			name: 'Todo 2',
			done: false,
		},
		{
			name: 'Todo 3',
			done: false,
		},	
		],
	},

Karena data todos sudah berpindah ke state, tentu cara memanggilnya dari dalam component sudah berbeda. Kita edit component todo dan tambahkan sebuah computed function todos untuk mengambil data todo dari state.

Vue.component('todo',{
	template: '<div class="container">'+
	'<div class="row justify-content-center">'+
	'<div class="col-md-6">'+
	'<h1 class="text-center">Todolist</h1>'+
	'<hr>'+
	'<input type="text" class="form-control" placeholder="Input todolist & enter" v-model="todo.name" v-on:keyup.enter="addTodo">'+
	'<hr>'+
	'<ul class="list-group">'+
	'<todo-item v-for="item,index in todos" v-bind:item="item" v-bind:key="index" ></todo-item>'+
	'</ul>'+
	'</div>'+
	'</div>'+
	'</div>',
	data: function(){
		return {
			status: 'all',
			todo: {
				name: '',
				done: false
			}
		}
	},
	computed: {
		todos(){
			return this.$store.state.todos
		},
	},
	methods: {
		addTodo(){
			
		}
	}
});

Sekarang coba buka aplikasi todolist di browser, harusnya kamu akan melihat tampilan seperti di bawah ini.

Tampilan Todolist dari Vuex

Merubah Event Create Todo, Toggle Todo dan Delete Todo

Karena kita sekarang menggunakan Vuex, jadi untuk melakukan perubahan pada state, harus menggunakan mutations. Buat 3 mutations yaitu addTodo, toggleTodo, dan deleteTodo

Edit store dan tambahkan 3 mutations tadi

mutations: {
	    addTodo (state,payload) {

	      state.todos.push(payload)

	    },

	    deleteTodo (state,payload) {

	      let index = state.todos.indexOf(payload);
	      state.todos.splice(index)

	    },

	    toggleTodo(state,payload){

	    	let index = state.todos.indexOf(payload);
	      	state.todos[index].done = !state.todos[index].done

	    }
	  },

Edit component todo-item dan ubah bagian methodnya dengan memanggil mutations dari store

Vue.component('todo-item',{
	props: ['item'],
	template: '<li class="list-group-item" v-bind:style="isActive">{{ item.name }}'+
	'<button type="button" class="btn btn-success float-right" v-on:click="toggleTodo">'+
	'&or;'+
	'</button>'+
	'<button type="button" class="btn btn-danger float-right" aria-label="Close" v-on:click="deleteTodo">'+
	'<span aria-hidden="true">&times;</span>'+
	'</button>'+
	'</li>',
	methods: {
		toggleTodo(){
			this.$store.commit('toggleTodo',this.item)
		},
		deleteTodo(){
			this.$store.commit('deleteTodo',this.item)
		}
	},
	computed: {
		isActive(){
			if(this.item.done){
				return 'text-decoration:line-through'
			}
		}
	}
});

Kita sudah hampir selesai.

Kamu bisa mencobanya sekarang, untuk menambah todo baru, enable & disable todo, maupun menghapus todo.

Langkah terkahir adalah saya mau menambahkan fungsi filter untuk menampilkan todolist yang sudah dikerjakan atau belum.

Pertama adalah membuat 2 buah getters di store yaitu doneTodospendingTodos

Edit store dan tambahkan getter di bawah ini

getters: {
		doneTodos(state){

			return state.todos.filter(function(item){
				return item.done == true
			})

		},
		pendingTodos(state){

			return state.todos.filter(function(item){
				return item.done == false
			})

		},
	},

Kita sudah memilik getters, saatnya melakukan filter di component. Buka component todo dan edit bagian template dan bagian computed.

Tambahkan beberapa button di template yang akan merubah value dari data status

.....
'<hr>'+
'<button @click="status='all'">All</button>'+
'<button @click="status='pending'">Pending</button>'+
'<button @click="status='done'">Done</button>'+
'<ul class="list-group">'+
.....

Buat sebuah data baru dengan nama status dengan default value = all. 

Edit bagian computed todos

todos(){
			
			if(this.status == 'all')
				return this.$store.state.todos	
			else if(this.status == 'done')
				return this.$store.getters.doneTodos
			else if(this.status == 'pending')
				return this.$store.getters.pendingTodos
		},

Jadi saat status berubah menjadi pending atau done, maka todos yang di panggil juga mengikuti apakah todo item tersebut statusnya pending atau done.

Nah sekarang saatnya mencoba aplikasi todolist yang sudah kita update sehingga memakai Vuex.

Kesimpulan

Jadi apa kesimpulan yang bisa kita ambil setelah mencoba mengimplementasikan Vuex sebagai state management di aplikasi todolist tersebut?

1. Data yang terpusat. Jadi karena datanya jadi 1 di dalam store maka lebih mudah untuk memanage dan maintenancenya. 

2. Semua component bisa mengakses state yang ada dan melakukan perubahan lewat mutations

3. Kalian tidak harus menggunakan Vuex jika scope projectnya tidak terlalu besar atau jika hanya dengan menggunakan props atau emit event saja cukup maka Vuex tidak diperlukan. Jika kalian membutuhkan state yang komplek yang harus dan mudah di akses oleh semua component maka Vuex bisa jadi pilihan wajib untuk kamu implementasikan.

Terakhir kamu wajib baca-baca lagi dokumentasi Vuex di sini: https://vuex.vuejs.org

Untuk project ini sudah saya upload di github, bisa di cek sini ya: vuex-todo

Semoga tutorial kali ini bermanfaat, silakan like & share ya.


Share Yuk:

Rekomendasi untuk di baca!


PHP : Variable, Tipe data, dan Operator

28 Oct 2014

Like our facebook page


Around Web