VueJs-#08b Vuex Mutations & Actions

Pendahuluan

Melanjutkan seri Tutorial Vuex, pada artikel sebelumnya telah dibahas bagaimana menggunakan state agar dapat digunakan oleh seluruh component yang ada. Maka pada artikel kali ini kita akan membahas bagaimana menggunakan Mutations dan Actions untuk mengelola dan melakukan perubahan data pada state.

Mutations bertugas untuk mengkonfirmasi setiap perubahan state yang akan dilakukan

Actions bertugas untuk memberikan perintah terhadap apa yang akan dilakukan. Misalnya saja, untuk melakukan perubahan data listAgenda, maka kita akan menyusun data yang akan di instruksikan ke Mutations agar melakukan perubahan pada state menggunakan perintah commit, meskipun kita dapat melakukan perubahan state secara langsung pada actions yang kita buat.

Persiapan

Pada tutorial VueJs State sebelumnya kita sudah membuat page dan component untuk menampilkan Agenda yang bernama AgendaShow. Sekarang kita buat sebuah component untuk menambahkan data bernama AgendaInput.vue berikut isi filenya:

<template>
    <div class="col-md-6">
        <div class="card">
            <div class="card-header">
                <h3 class="card-title">{{postTitle}}</h3>
            </div>
            <div class="card-body">
                <div class="form-group">
                    <label for="">Hari</label>
                    <input type="text" v-model="agenda.hari" class="form-control" required>
                </div>
                <div class="form-group">
                    <label for="">Kegiatan</label>
                    <input type="text" v-model="agenda.kegiatan" class="form-control" required>
                </div>
                <div class="form-group">
                    <button class="btn btn-danger btn-sm" @click.prevent="simpan">Tambahkan</button>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        name: 'AgendaInput',
        props: ['postTitle'],
        data() {
            return {
                agenda: {
                    hari: '',
                    kegiatan: ''
                }
            }
        },
        methods: {
            simpan() {
                
            }
        }
    }
</script>

Saya ingin menampilkan component AgendaInput.vue sebelum component AgendaShow.vue. Pada View views/LearningVuex.vue tambahkan component AgendaInput.vue seperti di bawah ini :

<template>
	<div id="app" class="container">
		<div class="row py-4">
			<agenda-input post-title="Input Agenda"/>
			<agenda-show post-title="Daftar Agenda"/>
		</div>
	</div>
</template>

<script>
	import AgendaInput from '../components/AgendaInput.vue'
	import AgendaShow from '../components/AgendaShow.vue'

	export default {
		name: 'app',
		components: {
			AgendaInput,
			AgendaShow
		}
	}
</script>

Hasilnya sebagai berikut:

+ Component AgendaInput

Actions dan Mutations

Hal pertama yang akan kita lakukan adalah memodifikasi bagian methods tambahkan simpan() pada component AgendaInput.vue, tambahkan code berikut:

methods: {
    simpan() {
        this.$store.dispatch('simpanAgenda', this.agenda)
        this.agenda = {
            hari: '',
            kegiatan: ''
        }
    }
}

Penjelasan

  • this.$store.dispatch(‘simpanAgenda’, this.agenda) akan memberikan instruksi pada actions dengan mengirimkan isi dari this.agenda yang di dapatkan dari data() yang telah di-input
  • this.agenda  berfungsi untuk mengosongkan form inputan setelah di submit.

Setelah itu buka file store.js dan tambahkan code berikut pada bagian actions :

actions: {
    simpanAgenda({ commit, state }, agenda) {
        state.isLoading = true
        setTimeout(() => {
            commit('KONFIRMASI_AGENDA', agenda)
            state.isLoading = false
        }, 1500)
    }
}

Penjelasan: fungsi simpanAgenda() memiliki dua parameter, parameter pertama yang diapit oleh kurung kerawal adalah fungsi yang dimiliki oleh Vuex, diantaranya: commit, state, rootState, dispatch, dan lain sebagainya.

Namun kami ini kita hanya akan menggunakan commit dan state saja. Sedangkan untuk parameter kedua akan menampung data yang dikirimkan dari yang meng-instruksikan, dalam hal ini adalah method dari component AgendaInput.vue. 

Line-2 mengakses state isLoading dan mengubah value-nya menjadi true (Note: Inilah cara mengubah state tanpa melalui mutations). 

Line-3 membuat fungsi setTimeout untuk mengatur setelah beberapa saat barulah fungsi selanjutnya dijalankan. 

Line-4 meng-instruksikan kepada mutations dengan fungsi commit(), dimana instruksi tersebut ditujukan pada KONFIRMASI_AGENDA yang terdapat pada mutations, parameter kedua dari commit berisi data yang akan dikirimkan. 

Line selanjutnya mengubah kembali nilai dari state isLoading menjadi false.

Ada dua bagian yang perlu diperhatikan, yakni adanya state isLoading dan mutations KONFIRMASI_AGENDA, baik, mari kita lengkapi satu persatu secara bertahap. Masih di dalam file store.js, pada bagian state, tambahkan code berikut:

state: {
    isLoading: false, //<=Kode yang ditambahkan
    agenda: [
        { hari: 'Senin', kegiatan: 'Belajar Vuejs' },
        { hari: 'Selasa', kegiatan: 'Belajar Laravel' },
        { hari: 'Rabu', kegiatan: 'Belajar Mysql' }
    ],
},

Kemudian pada bagian mutations, tambahkan code berikut:

mutations: {
    KONFIRMASI_AGENDA: (state, agenda) => {
        state.agenda.push(agenda)
    }
},

Penjelasan

KONFIRMASI_AGENDA memiliki dua parameter, parameter pertama adalah state untuk mengakses state yang ada. Sedangkan parameter kedua adalah value yang diterima dari yang meng-instruksikan. state.agenda berarti kita mengakses state listAgenda untuk kemudian ditambahkan data baru dengan fungsi push().

Sampai pada tahap ini, sudah dapat berfungsi sebagaimana mestinya. Tapi, kita menambahkan isLoading yang bertujuan untuk memberikan efek loading ketika tombol ditekan, maka buka file AgendaInput.vue, kemudian modifikasi pada tag button menjadi:

<button class="btn btn-danger btn-sm" :disabled="isLoading" @click.prevent="simpan">{{ isLoading ? 'Loading...':'Tambahkan' }}</button>

Masih di dalam file yang sama, tambahkan computed property berikut:

computed: {
    isLoading() {
        return this.$store.state.isLoading
    }
},

Jalankan

Masukan Hari: Minggu, Kegiatan: Libur, lalu klik tombol Tambahkan maka hasil yang akan diperoleh akan tampak seperti berikut :

Tambahkan Agenda

File lengkap :

file components/AgendaInput.vue

<template>
    <div class="col-md-6">
        <div class="card">
            <div class="card-header">
                <h3 class="card-title">{{postTitle}}</h3>
            </div>
            <div class="card-body">
                <div class="form-group">
                    <label for="">Hari</label>
                    <input type="text" v-model="agenda.hari" class="form-control" required>
                </div>
                <div class="form-group">
                    <label for="">Kegiatan</label>
                    <input type="text" v-model="agenda.kegiatan" class="form-control" required>
                </div>
                <div class="form-group">
                    <button class="btn btn-danger btn-sm"
                    :disabled="isLoading"
                    @click.prevent="simpan">{{ isLoading ? 'Loading...':'Tambahkan' }}</button>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        name: 'AgendaInput',
        props: ['postTitle'],
        data() {
            return {
                agenda: {
                    hari: '',
                    kegiatan: ''
                }
            }
        },
        computed: {
            isLoading() {
                return this.$store.state.isLoading
            }
        },
        methods: {
            simpan() {
                this.$store.dispatch('simpanAgenda', this.agenda)
                this.agenda = {
                    hari: '',
                    kegiatan: ''
                }
            }
        }
    }
</script>

file src/store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
      isLoading: false,
      agenda: [
        { hari: 'Senin', kegiatan: 'Belajar Vuejs' },
        { hari: 'Selasa', kegiatan: 'Belajar Laravel' },
        { hari: 'Rabu', kegiatan: 'Belajar Mysql' }
      ],
      listAgenda2: [
        { hari: 'Kamis', kegiatan: 'Belajar Nuxt' },
        { hari: "Jum'at", kegiatan: 'Belajar Flutter' },
      ]
  },
  mutations: {
    KONFIRMASI_AGENDA: (state, agenda) => {
        state.agenda.push(agenda)
    }
  },
  actions: {
    simpanAgenda({ commit, state }, agenda) {
      state.isLoading = true
      setTimeout(() => {
          commit('KONFIRMASI_AGENDA', agenda)
          state.isLoading = false
      }, 1500)
    }
  }
});

Kesimpulan

Actions dan Mutations dapat di-ibaratkan sebagai instruktur dan eksekutor, meskipun sang instruktur juga dapat mengeksekusi instruksinya sendiri. 3 Bagian penting (baca: statemutations dan actions) inilah yang memiliki banyak peranan dalam mengelola data menggunakan Vuex. Lalu bagaimana misalnya jika aplikasi yang sedang kita bangun sudah sangat kompleks? Jika code tersebut di gabungkan di dalam satu file yang sama, sebut saja store.js untuk mengelola datanya, maka akan sangat membingungkan jika sudah memiliki banyak code.


Sumber :

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>