Vuex best bractices when fetching data from the backend

Hello everyone!

I’m wondering what is the best practice for fetching remote data and the persisting it in vuex.
Like I see it there’s two possible ways to do this;

A. Use a getter to check if user has been fetched already, if not, dispatch an action to fetch it and commit the data to the local state.
B. Use a action to first check if the user exists by a getter, if not, fetch it and commit the data to the local state.

Which is the best way to go about this?

It would be nice to only have one method in the component for retrieving the user.
Eg, I don’t wanna have to first use the getter, validate its response, and then dispatch an action if there’s no data in the local store.

I would opt for a third way:

Before dealing with data, get a fresh copy from the server. Put it in vuex. After modification, post it to the server. On success refresh state in vuex. This way you minimize drift between your frontend and your backend.

Example: Editing users

  1. When route /usermanagement is entered a list of users is retrieved from the server
  2. When a single user is edited, the new version is sent to the server
  3. When (2) is successful, you could reload the list of users.

Your mileage may vary.

1 Like

I like how it’s done in the official Hackernews example.
They use an „ensure it’s there“ action beforehand.

Thanks for the reply!

Yeah, every time the component is rendered in for the first time and it needs the data I always to a fetch from the backend. I follow the steps of your example, and it works very well.

However, if a user does all of those three things, and then returns to /usermanagement at a later time, should I fetch the data from the backend again or just hit the vuex store since the data is there?

I usually use in component guards like beforeRouteEnter to retrieve a current version of the data.

As a rule of thumb, I use the DB as my primary source of truth and see vuex only as a secondary source. When in doubt, DB wins - so to say :wink:

This allows for a one directional flow of data.

This all makes sense to me but do you run into issues with the multiple round trips slowing down the SPA navigation then?

Although I understand the background of your question, it is not easy to answer:
Because the most obvious answers were the binary answers:

  • yes

  • no

Which only make sense in the context which you apply it.
If you have a query, which is heavy on the ressources, the obvious answer would be: yes, it does impact performace. But if you detect that and realize, that you could be more precise in your query and query only that data, which is really needed and your query becomes light again, the obvious answer is no, it doesn’t have an impact on the performace.

The overall question is: what is the goal. that you want to achieve and what are the roads towards this goal. If you say. you want a relative feeling of actuality (I omit writing “consistency”, since this would be a lie), you could go down this road.

OTOH: If you have a look at the “mobile” context, I wouldn’t want this to happen. In mobile context, a working and fast connection is always the bottleneck. So in this ecosystem my strategy would not work (as well). For mobile I would update only when essentially necessary.

@daniel1 what way did you end up going with?

I’m stuck in the same exact situation. Below is a snippet from my _.vue page component. Wondering if i should just do the check within the action itself

async asyncData(context) {

    const pathMatch =

      context.route.params.pathMatch === ''

        ? 'home'

        : context.route.params.pathMatch

    if (!context.store.getters['storyblok/pageInPages'](pathMatch)) {

      await context.store.dispatch('storyblok/loadStory', {

        context,

        slug: `pages/${pathMatch}`

      })

    }

    return {

      story: context.store.getters['storyblok/pageInPages'](pathMatch)

    }

  }

I ended up going with option B.
Dispatching an action that first checks if the resource is in the local store via it’s corresponding getter, if there’s no result I reach for the DB in the action and then set the local store data & return the response.

Works great in pretty much all cases.

1 Like