vuejs / pinia

🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support
https://pinia.vuejs.org
MIT License
13.07k stars 1.05k forks source link

Example with Axios #419

Closed jakenuts closed 3 years ago

jakenuts commented 3 years ago

Love this idea, npmtrends suggests I'm in good company. Would it be possible to provide a very simple example of updating the store from a rest data source? In my fever dreams there was already a pinia-axios plugin, but the Golden Girls & Farrag Fawcett were there in 60's bikin's so I got distracted.

posva commented 3 years ago

There is nothing particular about data fetching when it comes to stores. You can sure do it inside an action:

defineStore({
    state: () => ({ searchResults: [] }),
    actions: {
        async searchUsers(searchText) {
            this.searchResults = await axios.get('/api/users', { params: { searchText }})
        }
    }
})

But when doing SSR and using cookies (from the server), you must make sure to create an axios instance with the proper credentials on the server per request. But this isn't related to Stores, but rather to SSR (https://ssr.vuejs.org/), that's why Nuxt has modules like axios-nuxt.

I also use https://github.com/posva/mande for data fetching and it has a Nuxt module.

I have plans on adding documentation to handle modules like axios when doing SSR

BTW, make sure to use discussions for questions! I will add a link to the form now that discussions are available!

the Golden Girls & Farrag Fawcett were there in 60's bikin's so I got distracted.

What 😆 ?!

KayJay89 commented 3 years ago

Do you recommend defining the API calls in your store through actions? This was my preferred way of doing things in Vue 2 + Vuex & Axios and Typescript. (I know, I should probably have taken one step at a time lol)

I'm trying to shift over to Vue 3 & the new composition API while also trying to learn Pinia. I can't seem to find a good way to handle multiple, chained API calls (get) without getting a several errors. Am having a feeling this is more related to me not fully grasping the new composition API rather than Pinia though but this topic did piqued my interest. 😄

posva commented 3 years ago

Defining api calls in a store is fine if you store the data inside of it. If not, I personally expose plain functions that call the API.

Chaining API calls is mostly about Promises 🙂 Maybe you can find help if you share examples on the chat

KayJay89 commented 3 years ago

Yup that's exactly my use right now. I store everything inside it.

Just don't seem to be able to get it to react properly like I am used to without comp API + Vuex. I chained two promises where one relies on data (ids) from the first. I am able to get all data into my Pinia store (x-check Vue Devtools) but my component does not update at all. No matter what I try.

  setup() {
    const store = useParking()

    store.fetchParkingsData()

    return { parkings: computed(() => store.parkings) }

Really don't know if this is due to me not using Pinia correctly or I am missing something else.

posva commented 3 years ago

I can't tell from just that. If you have a boiled down reproduction, open a new issue 🙂

beetaa commented 3 years ago

Yup that's exactly my use right now. I store everything inside it.

Just don't seem to be able to get it to react properly like I am used to without comp API + Vuex. I chained two promises where one relies on data (ids) from the first. I am able to get all data into my Pinia store (x-check Vue Devtools) but my component does not update at all. No matter what I try.

  setup() {
    const store = useParking()

    store.fetchParkingsData()

    return { parkings: computed(() => store.parkings) }

Really don't know if this is due to me not using Pinia correctly or I am missing something else.

@KayJay89 @posva . I think the problem mostly because you've initialized the sub-component using something return from async calls. in that case, data in parkings still null or undefined. so the solution is waiting the real data arrived before the sub-component initialize. something like this:

<template>
  <ul v-if="parkings" :list-data="parkings">
    <li ...></li>
  </ul>
</template>

as you've seen, the most important part is the directive v-if.

hope can help.

gcgarciab commented 2 years ago

defineStore({ state: () => ({ searchResults: [] }), actions: { async searchUsers(searchText) { this.searchResults = await axios.get('/api/users', { params: { searchText }}) } } })

How I can test searchUsers action in a component ?, test that searchResults value is not [], and loads the async data. @posva

ryanwpb commented 2 years ago

You could try something like this...

`import axios from "axios"; import { defineStore } from "pinia";

export const useTodosStore = defineStore('todos', { state: () => ({ todos: [], loading: false }), actions: { addTodo(value) { this.todos.push(value) }, deleteTodo(value) { this.todos.splice(value, 1) } }, getters: { filterTodos: (state) => { return (value) => state.todos.filter((todo) => todo.title.includes(value)) }, async getTodos() { this.loading = true const response = await axios.get('http://jsonplaceholder.typicode.com/todos?_start=0&_limit=20') try { this.todos = await response.data; this.loading = false } catch (err) { this.todos = []; console.error('Error loading new Todos:', err); return err; } } } })`

khaledOghli commented 2 years ago

@posva @jakenuts I have a question, please . if I have Axios call in-store actions how can I call $toaster or $swal (sweet alert lib) inside a catch or inside then ?? and if it's not right in this way how can we handle this? please if there is an example!

defineStore({
    state: () => ({ searchResults: [] }),
    actions: {
        async searchUsers(searchText) {
            this.searchResults = await axios.get('/api/users', { params: { searchText }})
                        .then() { }
        }
    }
})
gregpalaci commented 1 year ago

await this.$nuxt.$axios.$get()