pinia 2

Bora Im·2024년 7월 29일

pinia

목록 보기
2/4

State (상태)

대부분의 경우, Store는 state를 중심으로 이루어지며, 일반적으로 앱의 state를 정의하는 것부터 시작합니다. Pinia에서 state는 초기 state를 반환하는 함수로 정의됩니다. 이것은 Pinia가 서버와 클라이언트 측에서 모두 작동할 수 있게 합니다.

export const useStore = defineStore('storeId', {
  // 완전한 타입 추론을 위해 화살표 함수를 사용하는 것이 좋습니다.
  state: () => {
    return {
      // 이 모든 프로퍼티들은 자동으로 타입이 추론됩니다.
      count: 0,
      name: 'Eduardo',
      isAdmin: true,
      items: [],
      hasChanged: true,
    }
  },
})

TypeScript

state를 TS와 호환되게 만들기 위해 많은 노력이 필요하지 않습니다. strict 또는 최소한 noImplicitThis를 활성화하면 Pinia가 state 타입을 자동으로 추론합니다! 하지만 몇 가지 경우에는 캐스팅으로 보조해야 합니다:

interface UserInfo {
  name: string
  age: number
}
export const useUserStore = defineStore('user', {
  state: () => {
    return {
      // 최초에 비어있는 배열의 경우.
      userList: [] as UserInfo[],
      // 아직 로드되지 않은 데이터의 경우.
      user: null as UserInfo | null,
    }
  },
})

원한다면, 인터페이스를 사용하여 state를 정의하고 state()의 반환 값에 타입을 지정할 수 있습니다:

interface State {
  userList: UserInfo[]
  user: UserInfo | null
}
interface UserInfo {
  name: string
  age: number
}
export const useUserStore = defineStore('user', {
  state: (): State => {
    return {
      userList: [],
      user: null,
    }
  },
})

state에 접근

기본적으로 store 인스턴스를 통해 직접 state에 접근하여 읽고 쓸 수 있습니다:

const store = useStore()

store.count++

state()에 정의하지 않은 새로운 프로퍼티를 추가할 수 없습니다. 최초에 state에 포함되어야 합니다. 예를 들어, secondCountstate()에 정의되어 있지 않다면, store.secondCount = 2를 실행할 수 없습니다.

state 재설정

Option Store에서는 Store의 $reset() 메서드를 호출하여 state를 초기 값으로 재설정할 수 있습니다.

const store = useStore()

store.$reset()

내부적으로 이것은 새로운 state 객체를 생성하기 위해 state() 함수를 호출하고 현재 state를 그것으로 대체합니다.

💡Setup Store에서는 직접 $reset() 메서드를 생성해야 합니다:

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)

  function $reset() {
    count.value = 0 // 초기화
  }

  return { count, $reset }
})

state 변경하기

store.count++로 Store를 직접 수정하는 것 외에도 $patch 메서드를 호출할 수 있습니다. 이 메서드를 사용하면 state일부 객체를 패치하여 여러 변경 사항을 동시에 적용할 수 있습니다.

store.$patch({ // 객체 형태
  count: store.count + 1,
  age: 120,
  name: 'DIO',
})

하지만 이 문법으로는 일부 변경 사항을 적용하기 어렵거나 비용이 많이 듭니다. 예를 들어, 배열에 요소를 추가하거나 제거 또는 splice 작업을 하는 등 컬렉션을 수정하려면 새 컬렉션을 생성해야 합니다. 이 때문에 $patch 메서드는 패치 객체로 적용하기 어려운 이러한 종류의 변경을 함수를 사용하여 그룹화할 수도 있습니다.

store.$patch((state) => { // 함수 형태
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})

주된 차이점은 $patch()가 여러 변경 사항을 devtools에서 하나의 항목으로 그룹화할 수 있다는 점입니다. 또한, state를 직접 변경하는 것과 $patch()는 모두 devtools에 나타나며 time travel이 가능합니다 (Vue 3의 devtools에서는 아직 지원되지 않습니다).

state 교체하기

Store의 state를 완전히 교체할 수는 없습니다. 그렇게 하면 반응성이 깨지기 때문입니다. 하지만 patch 할 수는 있습니다:

// ❌이것은 실제로 `$state`를 교체하지 않습니다.
store.$state = { count: 24 }
// 내부적으로 `$patch()`를 호출합니다:
store.$patch({ count: 24 })

pinia 인스턴스의 state를 변경하여, 전체 애플리케이션의 초기 state를 설정할 수도 있습니다. 이는 SSR State 하이드레이션에서 일반적으로 사용됩니다.

pinia.state.value = {}

state 구독하기

Vuex의 subscribe 메서드과 유사하게, Store의 $subscribe() 메서드를 통해 state 변화를 감지할 수 있습니다. watch()를 사용하는 것보다 $subscribe()를 사용시 장점은 subscribefetch 후에 한 번만 트리거된다는 점입니다 (예: 위에서 언급한 함수 방식을 사용할 때).

cartStore.$subscribe((mutation, state) => {
  mutation.type // 'direct' | 'patch object' | 'patch function'
  
  // cartStore.$id와 동일.
  mutation.storeId // 'cart'
  
  // mutation.type === 'patch object'인 경우에만 사용 가능.
  mutation.payload // cartStore.$patch()에 전달된 패치 객체

  // 변경될 때마다 전체 state를 로컬 저장소에 유지합니다.
  localStorage.setItem('cart', JSON.stringify(state))
})

기본적으로 state 구독은 컴포넌트에 추가한 경우에 바인딩됩니다 (Store가 컴포넌트의 setup() 내부에 있는 경우). 이는 해당 컴포넌트가 마운트 해제될 때 자동으로 제거됨을 의미합니다.
컴포넌트가 마운트 해제된 후에도 구독을 유지하려면 두 번째 인수로 { detached: true }를 전달하여 state 구독을 현재 컴포넌트에서 분리하십시오:

<script setup>
const someStore = useSomeStore()

// 이 구독은 컴포넌트가 마운트 해제된 후에도 유지됩니다.
someStore.$subscribe(callback, { detached: true })
</script>

🧐 특정 상태만 감시하고자 한다면 watch()가 적합하며, 스토어의 모든 상태 변화에 대한 포괄적인 감시가 필요하다면 $subscribe()를 사용할 수 있습니다.

  • watch()는 Vue 컴포지션 API의 기능으로, 특정 반응형 데이터나 계산된 속성을 관찰하고, 그 값이 변경될 때마다 실행됩니다. Pinia 상태도 반응형이므로 watch()를 사용할 수 있습니다.
    • 주로 특정 상태나 계산된 속성의 변화를 감지하고자 할 때 사용합니다.
    • 깊은 감시를 설정할 수 있어, 객체 내부의 속성 변화도 감지 가능합니다.
    • 스토어 외의 다른 반응형 데이터에도 사용할 수 있습니다.
  • $subscribe()는 Pinia에서 제공하는 메서드로, 스토어의 상태 변화에 반응할 수 있습니다. 주로 스토어의 상태 변화를 기록하거나 특정 로직을 실행할 때 사용됩니다.
    • Pinia 스토어에 특화된 구독 방식입니다.
    • 상태 변경의 유형(예: direct, patch object, patch function)에 대한 추가 정보를 제공합니다.
    • 주로 상태 변경을 로깅하거나, 특정 변경에 대한 처리 로직을 작성할 때 유용합니다.

0개의 댓글