Vue의 상태 관리 라이브러리로 State, Getters, Actions의 3가지 개념으로 동작한다.
vuex의 Mutation이 사라지고 modules도 기본적인 구조이므로 관리하지 않아도 된다.
npm i pinia
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
createApp(App).use(createPinia()).mount('#app')
/src/store/count.js 작성
이 때 count는 모듈이 된다.
import { defineStore } from 'pinia'
// 첫 번째 인수는 store 이름, 두 번째는 옵션들을 추가
// 함수를 반환
export const useCountStore = defineStore('count', {
state: () => ({
count: 1
}),
getters: {
double(state) {
return state.count * 2
}
},
actions: {
increase() {
this.count += 1
},
decrease() {
this.count -= 1
}
} // context가 없고 this로 모두 접근 가능
})
변수에 가져온 함수를 할당해서 해당 변수로 store를 참조
<script setup lang="ts">
import { useCountStore } from './store/count'
const countStore = useCountStore()
</script>
<template>
<h1>{{ countStore.count }}</h1>
<h1>{{ countStore.double }}</h1>
<button @click="countStore.increase">Increase</button>
<button @click="countStore.decrease">Decrease</button>
</template>
// /src/store/movie.ts
import { defineStore } from 'pinia'
export type Movies = Movie[]
export interface Movie {
Title: string
Year: string
imdbID: string
Type: string
Poster: string
}
export const useMovieStore = defineStore('movie', {
state: () => ({
movies: [] as Movies // 빈 배열은 never 타입으로 인식되기 때문에 단언을 해줌
}),
getters: {
filteredMovies(state) {
return state.movies
.filter((movie) => Number(movie.Year) > 2010)
.sort((a, b) => Number(b.Year) - Number(a.Year))
}
},
actions: {
async fetchMovies(title: string) {
const res = await fetch(`https://omdbapi.com/?apikey=7035c60c&s=${title}`)
const { Search } = await res.json()
this.movies = Search
}
}
})
$reset() 함수를 사용하면 해당 store의 모든 state를 초기화 시킨다.
// App.vue
<script setup lang="ts">
import { ref } from 'vue'
import { useMovieStore } from './store/movie'
const movieStore = useMovieStore()
const title = ref('')
async function searchMovies() {
await movieStore.fetchMovies(title.value)
console.log(movieStore.movies)
}
function resetMovies() {
title.value = ''
movieStore.$reset() // movieStore가 가지고 있는 모든 state를 초기화
console.log(movieStore.movies)
}
</script>
<template>
<input
v-model="title"
@keydown.enter="searchMovies" />
<button @click="searchMovies">Search</button>
<button @click="resetMovies">Reset</button>
<ul>
<li
v-for="movie in movieStore.filteredMovies"
:key="movie.imdbID">
{{ movie.Title }}
{{ movie.Year }}
</li>
</ul>
</template>