본문 바로가기

Java Scripts/Vue.js

Vuex - Mutation & Action - 1

728x90

Mutations

use Mutations to update, or mutate, our State.

상태를 업데이트하거나 변경하려면 Mutations를 사용하세요.

For simple examples, State has a count property

간단한 예를 들어 State에는 count 속성이 있습니다.

 

store.js

    state: {
      count: 0
    }

 

 

store.js

mutation can allow us to increment that value

mutation 를 통해 해당 값을 늘릴 수 있습니다.

INCREMENT_COUNT mutation is taking in our Vuex state as an argument and using it to increment the count.

INCREMENT_COUNT 변이는 Vuex state 를 인수로 사용하여 개수를 증가시킵니다.

    mutations: {
      INCREMENT_COUNT(state) {
        state.count += 1
      }
    }

commit that Mutation from within a component in the method property.

method  속성의 component 내에서 해당 Mutation을 commit 합니다.

    incrementCount() {
      this.$store.commit('INCREMENT_COUNT')
    },

Dynamic Mutations

Pass in a payload to a Mutation to make it dynamic.

페이로드를 Mutation에 전달하여 동적으로 만듭니다.

For example, add an input to our template and use v-model to bind it to a new data property.

and use the .number modifier to typecast the input value as a number.

예를 들어 템플릿에 input element를 추가하고 v-model을 사용하여 이를 새 데이터 속성에 바인딩합니다.
.number modifier 를 사용하여 입력 값을 숫자로 타입캐스트합니다.

  <input type="number" v-model.number="incrementBy">
    data() {
      return {
        incrementBy: 1
      }
    }

pass in the incrementBy value from our data as a payload when we commit our Mutation.

Mutation을 커밋할 때 데이터의 incrementBy 값을 페이로드로 전달합니다.

    incrementCount() {
      this.$store.commit('INCREMENT_COUNT', this.incrementBy)
    },

In Vuex Store, INCREMENT_COUNT Mutation can receive that payload in its second argument and 

use it to update our count dynamically.

Vuex Store에서 INCREMENT_COUNT Mutation은 두 번째 인수로 해당 페이로드를 수신할 수 있으며
이를 사용하여 개수를 동적으로 업데이트합니다.

    INCREMENT_COUNT(state, value) {
      state.count += value
    }

 

Actions

  • While Vuex Mutations are synchronous. Actions can be asynchronous. which contains multiple steps that actually happen in an order different from the order in which they are written.
  • Vuex Mutations는 동기식입니다. Actions은 비동기식일 수 있습니다. 여기에는 작성된 순서와 다른 순서로 실제로 발생하는 여러 단계가 포함되어 있습니다.
  • Actions can wrap some business logic around a Mutation, or Mutations.
  • Actions은 Mutation 또는 Mutations에 주변의 일부 비즈니스 로직을 래핑할 수 있습니다.
  • Mutations within an Action may or may not be committed, depending on how the surrounding logic and circumstances pan out.
  • 주변 논리와 상황이 어떻게 전개되는지에 따라 Action 내의 Mutation이 커밋될 수도 있고 그렇지 않을 수도 있습니다.

 

Seeing them in Action

some updates happen to the counter example above. 

위의 카운터 예에 일부 업데이트가 발생합니다.

It is using object destructuring to get state and commit from the Vuex context object: { state, commit }.

Vuex 컨텍스트 객체에서 상태와 커밋을 가져오기 위해 object destructuring를 사용하고 있습니다.

The context object is the first argument of any Action, and it exposes the same set of properties that are on the store instance (state, mutations, actions, getters). 

컨텍스트 개체는 모든 작업의 ​​첫 번째 인수이며 store 인스턴스에 있는 것과 동일한 속성 집합을 노출합니다.

note) store.state store.commit 가  { state, commit } 로 assign 된다.

    actions: {
      updateCount({ state, commit }, incrementBy) {
        if (state.user) {
          commit('INCREMENT_COUNT', incrementBy)
        } 
    }

Within our component, we’d dispatch the Action, which is what commits the Mutation.

component 내에서 Mutation을 커밋하는 Action을 전달합니다.

    incrementCount() {
      this.$store.dispatch('updateCount', this.incrementBy)
    },

It is recommended to always commit a Mutation from within an Action.

항상 Action 내에서 Mutation 를 커밋하는 것이 좋습니다.

 

Adding to Our Example App

  • Want a user to be able to create a new event, too, which is added, or stored, within the Vuex Store.
  • 사용자가 Vuex Store 내에 추가되거나 저장되는 새 이벤트도 만들 수 있기를 원합니다.
  • Add a Mutation and commit it from an Action.
  • Mutation을 추가하고 Action에서 커밋합니다.

Creating Events

we’re asking a series of questions and using v-model on input elements to bind the user’s responses to our data.

우리는 일련의 질문을 하고 input elements에 v-model을 사용하여 사용자의 응답을 데이터에 바인딩합니다.

        <form>
          <label>Select a category</label>
          <select v-model="event.category">
            <option v-for="cat in categories" :key="cat">{{ cat }}</option>
          </select>
          <h3>Name & describe your event</h3>
          <div class="field">
            <label>Title</label>
            <input v-model="event.title" type="text" placeholder="Add an event title"/>
          </div>
          <div class="field">
            <label>Description</label>
            <input v-model="event.description" type="text" placeholder="Add a description"/>
          </div>
          <h3>Where is your event?</h3>
          <div class="field">
            <label>Location</label>
            <input v-model="event.location" type="text" placeholder="Add a location"/>
          </div>
          <h3>When is your event?</h3>
          <div class="field">
            <label>Date</label>
            <datepicker v-model="event.date" placeholder="Select a date"/>
          </div>
          <div class="field">
            <label>Select a time</label>
            <select v-model="event.time">
              <option v-for="time in times" :key="time">{{ time }}</option>
            </select>
          </div>
          <input type="submit" class="button -fill-gradient" value="Submit"/>
        </form>

whole script sction of this components

이 구성 요소의 전체 스크립트 섹션

    <script>
    import Datepicker from 'vuejs-datepicker'
    export default {
      components: {
        Datepicker
      },
      data() {
        const times = []
        for (let i = 1; i <= 24; i++) {
          times.push(i + ':00')
        }
        return {
          event: this.createFreshEvent(),
          times,
          categories: this.$store.state.categories,
        }
      },
      methods: {
        createFreshEvent() {
          const user = this.$store.state.user
          const id = Math.floor(Math.random() * 10000000)
          return {
            id: id,
            category: '',
            organizer: user,
            title: '',
            description: '',
            location: '',
            date: '',
            time: '',
            attendees: []
          }
        }
      }
    }
    </script>

importing the new datepicker and registering it as a child component

새 날짜 datepicker를 가져오고 이를 하위 component 로 등록

    import Datepicker from 'vuejs-datepicker'
    export default {
      components: {
        Datepicker
      }

data() is a function, which is capable of performing some initial data-based logic within it.

data()는 그 안에서 초기 데이터 기반 논리를 수행할 수 있는 함수입니다.

times } is the same as { times: times }.

    data() {
      const times = []
      for (let i = 1; i <= 24; i++) {
        times.push(i + ':00')
      }
      return {
        ...
        times
      }

Generates a fresh event object whenever this component is created.

이 component가 생성될 때마다 새로운 이벤트 객체를 생성합니다.

When we submit an event, we want to reset this component’s event data, and this method is a handy way.

이벤트를 제출할 때 이 구성요소의 이벤트 데이터를 reset 하려고 하는데 이 방법이 편리한 방법입니다.

    createFreshEventObject() {
      const user = this.$store.state.user
      const id = Math.floor(Math.random() * 10000000)
      return {
        id: id,
        category: '',
        organizer: user,
        title: '',
        description: '',
        location: '',
        date: '',
        time: '',
        attendees: []
      }
    }

The ADD_EVENT Mutation

It receives an event argument, then pushes it onto our events state.

이벤트 argument를 받은 다음 이를 이벤트 state로 푸시합니다.

    ADD_EVENT(state, event) {
      state.events.push(event)
    },

The createEvent Action

Our Action is using the EventService we created in our API Calls with Axios in order to do a POST request with postEvent(event),

Action은 postEvent(event)로 POST 요청을 수행하기 위해 Axios를 사용하여 API 호출에서 생성한 EventService를 사용하고 있습니다.

    createEvent({ commit }, event) {
      EventService.postEvent(event)
      commit('ADD_EVENT', event)
    })

EventService.js

It receives an event and can POST it to this endpoint, where our mock events database lives.

이벤트를 수신하고 이를 모의 이벤트 데이터베이스가 있는 이 엔드포인트에 POST 할 수 있습니다.

    postEvent(event) {
      return apiClient.post('/events', event)
    }

Dispatching the eventCreate Action

In EventCreate component,  add a method that will dispatch our new Action.

EventCreate 구성 요소에서 새 작업을 전달하는 메서드를 추가합니다.

    methods: {
      createEvent() {
        this.$store.dispatch('createEvent', this.event)
      },
    ...

Trigger this method when our form is submitted

양식이 제출될 때 이 메서드를 트리거합니다.

    <form  @submit.prevent="createEvent">

Resetting our Event Data

we want to reset our component’s event data object every time a new event is submitted.

새 이벤트가 제출될 때마다 구성 요소의 이벤트 데이터 개체를 reset 하려고 합니다.

 createEvent() {
 	this.$store.dispatch('createEvent', this.event)
 	this.event = this.createFreshEventObject()
 }

Problem: But we don’t want to clear out our event until we know it’s been added to our backend.

하지만 우리는 이벤트가 백엔드에 추가되었다는 것을 알기 전까지는 이벤트를 지우고 싶지 않습니다.

What if our user was creating an event, clicked submit, stepped onto an elevator and the event never submitted.

사용자가 이벤트를 생성하고 제출을 클릭하고 엘리베이터를 탔는데 이벤트가 제출되지 않았다면 어떻게 될까요?

 

Solution : In our Action, return the response from our API. And .then commit our Mutation.

작업에서 API의 응답을 반환하고. 그런 다음 Mutation를 커밋합니다.

when the event is successfully POSTed, commit ADD_EVENT.

이벤트가 성공적으로 POST되면 ADD_EVENT를 커밋합니다.

    createEvent({ commit }, event) {
      return EventService.postEvent(event).then( () => {
          commit('ADD_EVENT', event.data)
        })
    }

Only reset our event data (this.event) if the POST request was a success.

POST 요청이 성공한 경우에만 이벤트 데이터(this.event)를 재설정하세요.

    createEvent() {
      this.$store.dispatch('createEvent', this.event)
        .then(() => {
          this.event = this.createFreshEventObject()
        })
        .catch(() => {
          console.log('There was a problem creating your event.')
        })
    }

If the POST request was not a success, we’ll log an error to the console. Next cover how to effectively display this error to the user.

POST 요청이 성공하지 못한 경우 콘솔에 오류가 기록됩니다. 다음에서는 이 오류를 사용자에게 효과적으로 표시하는 방법을 다룹니다.

 

Routing to our New Event

  • Route our user to the event-show page for the event they just created.
  • 방금 생성한 이벤트에 대한 이벤트 표시 페이지로 사용자를 라우팅합니다.
  • Clear the event after we strip the id from it for our router params.
  • 라우터 매개변수에 대한 ID를 제거한 후 이벤트를 지웁니다.
    createEvent() {
      this.$store
        .dispatch('createEvent', this.event)
        .then(() => {
          this.$router.push({
            name: 'event-show',
            params: { id: this.event.id }
          })
          this.event = this.createFreshEventObject()
        })
        .catch(() => {
          console.log('There was a problem creating your event.')
        })
    }

Adjusting EventShow

adjust the EventShow component’s template so it doesn’t display our entire user object for the event organizer.

이벤트 주최자에 대한 전체 사용자 개체가 표시되지 않도록 EventShow 구성 요소의 템플릿을 조정합니다.

<h5>Organized by {{ event.organizer ? event.organizer.name : '' }}</h5>

 

Resources

Mutations | Vuex (vuejs.org)

 

Mutations | Vuex

Mutations The only way to actually change state in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string type and a handler. The handler function is where we perform actual state modifications, and

vuex.vuejs.org

https://vuex.vuejs.org/guide/actions.html

 

Actions | Vuex

Actions Actions are similar to mutations, the differences being that: Instead of mutating the state, actions commit mutations.Actions can contain arbitrary asynchronous operations. Let's register a simple action: const store = createStore({ state: { count:

vuex.vuejs.org

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring

 

Destructuring assignment - JavaScript | MDN

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

developer.mozilla.org

https://router.vuejs.org/guide/essentials/navigation.html

 

Programmatic Navigation | Vue Router

Programmatic Navigation Aside from using to create anchor tags for declarative navigation, we can do this programmatically using the router's instance methods. Navigate to a different location Note: Inside of a Vue instance, you have access to the router i

router.vuejs.org

https://github.com/Code-Pop/real-world-vue/releases/tag/lesson12-mutations%26actions1-finish

 

Release lesson12-mutations&actions1-finish · Code-Pop/real-world-vue

dot should be dash

github.com

 

'Java Scripts > Vue.js' 카테고리의 다른 글

Vue : Programmatic Navigation  (0) 2022.04.30
Vuex - Mutation & Action - 2  (0) 2022.04.18
Vue MultiSelect  (0) 2022.04.09
Vue 3 -Teleport  (0) 2022.03.22
Vue : Error Handling and 404s  (0) 2022.01.16