Actions는 컴포넌트의 메서드와 동일합니다. defineStore()에서 actions 프로퍼티로 정의할 수 있으며, 처리해야 할 작업의 로직을 정의하는 데 완벽합니다:
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
// `this`에 의존하므로 화살표 함수를 사용할 수 없습니다.
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
Getters와 마찬가지로 actions도 this를 통해 전체 Store 인스턴스에 접근할 수 있으며, 완벽한 타입 지원(및 자동 완성 ✨)을 제공합니다. Getters와 달리 actions는 비동기적일 수 있으며, actions 내부에서 API 호출이나 다른 actions를 await할 수 있습니다!
여기 Mande를 사용하는 예제가 있습니다. 어떤 라이브러리를 사용하는지는 중요하지 않으며, Promise를 얻을 수 있으면 됩니다. 심지어 원시 fetch 함수(브라우저 전용)를 사용할 수도 있습니다:
import { mande } from 'mande'
const api = mande('/api/users')
export const useUsers = defineStore('users', {
state: () => ({
userData: null,
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`환영합니다, ${this.userData.name}!`)
} catch (error) {
showTooltip(error)
// 폼 컴포넌트가 오류를 표시하도록 합니다.
return error
}
},
},
})
Actions는 원하는 인수를 자유롭게 설정하고 원하는 결과를 반환할 수 있습니다.
Actions를 호출할 때 모든 것이 자동으로 추론됩니다!
Actions는 일반 함수나 메서드처럼 호출됩니다:
<script setup>
const store = useCounterStore()
// Action을 Store의 메서드로 호출합니다.
store.randomizeCounter()
</script>
<template>
<!-- 템플릿에서도 가능합니다. -->
<button @click="store.randomizeCounter()">Randomize</button>
</template>
다른 Store를 사용하려면 action 내부에서 직접 사용하면 됩니다:
import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', {
state: () => ({
preferences: null,
}),
actions: {
async fetchUserPreferences() {
const auth = useAuthStore()
if (auth.isAuthenticated) {
this.preferences = await fetchPreferences()
} else {
throw new Error('인증이 필요합니다')
}
},
},
})
store.$onAction()을 사용하여 actions와 그 결과를 감시할 수 있습니다.
after 훅 함수는 action에서 return 또는 promise 완료(resolve) 이후 실행됩니다. onError 훅 함수는 action이 오류를 발생(throw)시키거나 promise 실패(reject)할 때 실행됩니다.여기 실행 전과 action이 resolve/reject된 후에 로그를 기록하는 예제가 있습니다.
const unsubscribe = someStore.$onAction(
({
name, // action 이름.
store, // Store 인스턴스, `someStore`와 같음.
args, // action으로 전달된 매개변수로 이루어진 배열.
after, // action에서 return 또는 resolve 이후의 훅.
onError, // action에서 throw 또는 reject 될 경우의 훅.
}) => {
// 특정 action 호출 시 사용할 변수를 정의합니다.
const startTime = Date.now()
// 이것은 `store`의 action이 실행되기 전에 트리거됩니다.
console.log(`"${ name }"가 [${ args.join(', ') }] 인자를 전달받아 시작됩니다.`)
// 이것은 action이 끝까지 실행된 후에 트리거됩니다.
// 반환된 promise를 기다립니다.
after((result) => {
console.log(`"${ name }"가 ${Date.now() - startTime}ms 후 종료됐습니다.\n결과: ${ result }.`)
})
// action이 throw 되거나 promise가 reject되면 트리거됩니다.
onError((error) => {
console.warn(`"${ name }"가 ${Date.now() - startTime}ms 후 실패했습니다.\n에러: ${ error }.`)
})
}
)
// 리스너를 수동으로 제거합니다.
unsubscribe()
기본적으로 action 구독은 컴포넌트에 추가한 경우에 바인딩됩니다 (Store가 컴포넌트의 setup() 내부에 있는 경우). 이는 해당 컴포넌트가 마운트 해제될 때 자동으로 제거됨을 의미합니다.
컴포넌트가 마운트 해제된 후에도 구독을 유지하려면 action 구독의 두 번째 인수로 true를 전달하여 현재 컴포넌트에서 분리하십시오:
<script setup>
const someStore = useSomeStore()
// 이 구독은 컴포넌트가 마운트 해제된 후에도 유지됩니다.
someStore.$onAction(callback, true)
</script>