이 글은 Vue 3의 공식 Store | Pinia 를 보고 정리한 글입니다.
더 자세한 내용을 원하시면 공식 문서를 참고하세요.
컴포넌트의 method와 동일한 일을 합니다.
이들은 defineStore()에서 actions속성으로 정의할 수 있으며, 처리해야 할 작업의 로직을 정의하는데 완벽합니다 :
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
// `this`에 의존하므로, 화살표 함수를 사용할 수 없음.
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
getter와 마찬가지로 액션은 전체 입력(및 자동 완성 ✨) 지원과 함께 this를 통해 전체 스토어 인스턴스에 접근할 수 있습니다. getter와 달리 actions은 비동기식일 수 있으며, action 내에서 API 호출이나 다른 action을 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)
// 폼(form) 컴포넌트가 오류를 표시하도록 함.
return error
}
},
},
})
또한 원하는 인자를 자유롭게 설정하고, 무엇이든 return 할 수 있습니다. action을 호출하면 모든 것이 자동으로 추론됩니다.
action 은 method처럼 호출됩니다 :
export default defineComponent({
setup(){
const store = useCounterStore()
//스토어의 action을 method 처럼 호출
store.randomizeCounter()
return {}
}
})
다른 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('인증이 필요합니다!')
}
},
},
})
setup()에서 사용
export default {
setup() {
const store = useCounterStore()
store.randomizeCounter()
},
}
Option API에서 사용
// 예제 파일 경로:
// ./src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++
}
}
})
setup() hook을 사용하면 Option API에서 피니아를 더 쉽게 사용할 수 있습니다. 추가 map Helper 함수가 필요하지 않습니다.
import { useCounterStore } from '../stores/counter'
export default {
setup() {
const counterStore = useCounterStore()
return { counterStore }
},
methods: {
incrementAndPrint() {
this.counterStore.increment()
console.log('숫자세기:', this.counterStore.count)
},
},
}
Composition API를 전혀 사용하지 않고 mapActions() Helper를 사용하여 Component의 method에 action 속성을 mapping 할 수 있습니다 :
import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counter'
export default {
methods: {
// 컴포넌트 내부에서 `this.increment()`로 접근할 수 있게 함.
// `store.increment()`처럼 호출하는 것과 동일.
...mapActions(useCounterStore, ['increment']),
// 위와 같지만 `this.myOwnName()`으로 등록.
...mapActions(useCounterStore, { myOwnName: 'increment' }),
},
}
action 구독하기
store.$onAction()에 콜백을 전달해 액션과 그 결과를 감시할 수 있으며, 액션보다 먼저 실행됩니다.
after는 프라미스(promise)를 처리하고, 액션이 해결(resolve)된 후, 함수를 실행할 수 있도록 합니다. 비슷한 방식으로 onError를 사용하면, 작업이 실패(throw)되거나 거부(reject)되는 경우, 함수를 실행할 수 있습니다. 이는 Vue 문서에서 언급하는 팁과 유사하게 런타임에 오류를 추적하는 데 유용합니다.
다음은 액션을 실행하기 전과 해결/거부 이후를 콘솔에 기록하는 예제입니다.
const unsubscribe = someStore.$onAction(
({
name, // 액션의 이름.
store, // 스토어 인스턴스, `someStore`와 같음.
args, // 액션으로 전달된 인자로 이루어진 배열.
after, // 액션에서 반환 또는 해결 이후의 훅.
onError, // 액션에서 실패 또는 거부될 경우의 훅.
}) => {
// 이 특정 액션 호출에 대한 공유 변수.
// 역자설명: 이 액션의 훅에서 참조하게 되는 클로저 변수 개념.
const startTime = Date.now()
// 이곳은 `store`의 액션이 실행되기 전에 트리거됨.
console.log(`"${name}"가 [${args.join(', ')}] 인자를 전달받아 시작됩니다.`)
// 액션이 성공하고 완전히 실행된 후에 트리거됨.
// 프라미스 반환을 대기.
after((result) => {
console.log(
`"${name}"가 ${
Date.now() - startTime
}ms 후 종료됬습니다.\n결과: ${result}.`
)
})
// 액션이 실패하거나 프라미스가 거부되면 트리거 됨.
onError((error) => {
console.warn(
`"${name}"가 ${
Date.now() - startTime
}ms 후 실패했습니다.\n애러: ${error}.`
)
})
}
)
// 리스너를 수동으로 제거.
unsubscribe()
기본적으로 액션 구독은 컴포넌트에 추가된(스토어가 컴포넌트의 setup() 내부에 있는) 경우에 바인딩됩니다. 따라서 컴포넌트가 마운트 해제되면 자동으로 제거됩니다. 컴포넌트가 마운트 해제된 후에도 이를 유지하려면, 두 번째 인수로 현재 컴포넌트에서 액션 구독을 분리하는 true를 전달합니다:
export default {
setup() {
const someStore = useSomeStore()
// 이 구독은 컴포넌트가 마운트 해제된 후에도 유지됨.
someStore.$onAction(callback, true)
// ...
},
}
'IT > Pinia' 카테고리의 다른 글
Vue3 ) script setup (0) | 2023.03.28 |
---|---|
Pinia - Getter ( Option Store ) (0) | 2023.01.02 |
Pinia - State ( Option Store ) (0) | 2023.01.02 |
Pinia (0) | 2022.12.30 |