Lidando com Funções de Composição
As funções de composição são funções aproveitam a API de Composição da Vue para encapsular e reutilizar a lógica com estado. Quer escrevamos as nossas próprias bibliotecas, usemos bibliotecas externas ou façamos ambas, podemos usar plenamente o poder das funções de composição nas nossas memórias da pinia.
Memórias de Opções
Quando definimos uma memória de opções, podemos chamar função de composição dentro da propriedade state
:
export const useAuthStore = defineStore('auth', {
state: () => ({
user: useLocalStorage('pinia/auth/login', 'bob'),
}),
})
Tenha em mente que só podemos retornar estado gravável (por exemplo, uma ref()
). Eis alguns exemplos de funções de composição que podemos usar:
Eis alguns exemplos de funções de composição que não podem ser usadas em memórias de opções (mas podem ser usadas com as memórias de configuração):
useMediaControls
: expõe funçõesuseMemoryInfo
: expõe dados que só podem ser lidosuseEyeDropper
: expõe dados e funções que só podem ser lidos
Memórias de Configuração
Por outro lado, ao definir uma memória de configuração, podemos usar quase qualquer função de composição, uma vez que cada propriedade é discernida por um estado, uma ação ou recuperadora:
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'
export const useVideoPlayer = defineStore('video', () => {
// não exporemos (retornaremos) este elemento diretamente
const videoElement = ref<HTMLVideoElement>()
const src = ref('/data/video.mp4')
const { playing, volume, currentTime, togglePictureInPicture } =
useMediaControls(videoElement, { src })
function loadVideo(element: HTMLVideoElement, src: string) {
videoElement.value = element
src.value = src
}
return {
src,
playing,
volume,
currentTime,
loadVideo,
togglePictureInPicture,
}
})
AVISO
Diferente do estado normal, ref<HTMLVideoElement>()
contém uma referência que não é normalizável para o elemento do DOM. É por isso que não a retornamos diretamente. Já que é um estado apenas para o cliente, sabemos que este não será definido no servidor e sempre começará como undefined
no cliente.
Interpretação do Lado do Servidor
Quando lidamos com a Interpretação do Lado do Servidor, precisamos de ter em atenção alguns passos adicionais para podermos usar as funções de composição nas nossas memórias.
Nas Memórias de Opções, precisamos definir uma função hydrate()
. Esta função é chamada quando uma memória é instanciada no cliente (o navegador) quando existe um estado inicial disponível no momento em que a memória é criada. A razão pela qual precisamos definir essa função é porque, neste cenário, state()
não é chamada:
import { defineStore, skipHydrate } from 'pinia'
import { useLocalStorage } from '@vueuse/core'
export const useAuthStore = defineStore('auth', {
state: () => ({
user: useLocalStorage('pinia/auth/login', 'bob'),
}),
hydrate(state, initialState) {
// neste caso, podemos ignorar completamente o estado
// inicial, uma vez que queremos ler o valor do navegador
state.user = useLocalStorage('pinia/auth/login', 'bob')
},
})
Nas Memórias de Configuração, precisamos usar uma auxiliar chamada skipHydrate()
em qualquer propriedade de estado que não deva ser retirada do estado inicial. Diferentemente das memórias de opções, as memórias de configuração não podem simplesmente pular a chamada state()
, então marcamos as propriedades que não podem ser hidratadas com skipHydrate()
. Nota que isto só se aplica as propriedades reativas graváveis:
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'
export const useColorStore = defineStore('colors', () => {
const { isSupported, open, sRGBHex } = useEyeDropper()
const lastColor = useLocalStorage('lastColor', sRGBHex)
// ...
return {
lastColor: skipHydrate(lastColor), // Ref<string>
open, // Function
isSupported, // boolean (nem sequer reativo)
}
})