Search code examples
vue.jsvue-composition-apipinia

Pinia Vue Composition API, accessing state returns undefined


I have this Pinia store defined as:

export const useNotesStore = defineStore('notes', () => {
  const initialData = computed(() => ({
    banner: "",
    title: "",
    group: "",
    newGroup: "",
    content: "",
    favorite: false,
  }))
  const newNote = ref({ ...initialData.value });
  const parsed = JSON.parse(localStorage.getItem("notes")) || [];
  const notes = ref([...parsed]);

  const addNote = (payload) => {};

  return {
    initialData,
    newNote,
    notes,
    addNote,
  };
});

And, I am importing and using the store in my page as follows:

import { useNotesStore } from '@/stores/notes';
const notesStore = useNotesStore();

const handleSelectBanner = (value) => {
    // If I simply log, it has values.
    console.log(notesStore.newNote);

    // this line right here is what's throwing an error.
    notesStore.newNote.value.banner = value;

}

This is the output when logging notesStore.newNote.

Proxy(Object) {banner: '', title: '', group: '', newGroup: '', content: '', …}

However, when I handle button click in my template, and access the state in my Pinia. I get an error:

Uncaught TypeError: Cannot set properties of undefined (setting 'banner')

Afaik, when we access the state, we always use .value, but why is mine undefined? Is there something I am missing here?

PS: I am learning Pinia with Vuejs.


Solution

  • Okay so I figured it out.

    Even though the newNotes state of our Pinia is reactive with ref({ ... }), we do not access its value using .value outside of the store, instead, we use the state directly like the below:

    const notesStore = useNotesStore();
    notesStore.newNotes.banner = 'Your Value Here';
    

    This is because the Pinia store will unwrap that for us.

    However, we still need to use .value if we access the state INSIDE the store like:

    
    // this is a method defined in the store.
    const addNote = (payload) => {
         notes.value.push(payload);
    };
    

    I'll just leave the post here as it might help others with similar problem.