Structuring Vuex Modules for Relationships, Speed and Flexibility

You can use Vuex modules in many ways, primarily representing single or multiple records. When using the latter it can add a lot of complexity, I wanted a solution that fit the following requirements:

  • Easy lookup by ID
  • Relatable to other records (only when required)
  • Responsive to changes
  • Fast

I benchmarked a bunch of solutions but I found them pretty slow, so I used a more vanilla approach. This article assumes you are able to transpile code with Webpack for multiple browser support.


Basic Module Layout

This module describes a hypothetical albums recordset (along with artists and songs referenced elsewhere).

I store all the records in .all, but I convert the array of listings to an object. This is for two reasons:

  • I can efficiently query a record by an ID
  • Converting back to an array (with Object.values) for iteration is pretty fast

Fetching an Individual Record

Now that we are storing records in an object (Indexed by ID) we can easily fetch a record by that ID.

A method to fetch a specific album

Listing & Querying Records

We can iterate through many records by using Object.values of the state.all variable. You can also apply a .filter() on the array for querying specific data.

Examples using computed properties

Relationships

Relationships are used primarily to augment listings. Here are some examples using computed properties.

Adding relationship data based on the context requirements is a lot more effective than populating that data all the time as some libraries do.


Active Record Pattern

I use an .active variable to keep track of what record I am currently editing/focused on. This has a few advantages:

  • Standard across all modules
  • Simplifies updates and API integration

To use it you must $store.commit(‘albums/active’, 123)


Edit: Maintaining Record Order

This is really meant to query by ID’s but sometimes the order of the original array will be important. When you convert an array to object and back to an array Javascript will not guarantee the same order. If the order of records is important you can change the add all action to append the order to the records:

Add an order to the record values for sorting

Now we can sort by when listing:

This sort assumes all the order values are different

Bonus: API Integration Actions

It is important to keep client and server records synced up. These Vuex actions integrate saving to the server and ensuring the client side represents what is saved including potential server changes. This example shows my API library in use passing in the active user module for authorization.

This example builds on the above basic layout

When I made any modification to a record I return all relevant information again so I can trust that what is on the server is on the client side.


Hopefully, you will ignore the shortcuts in syntax, thanks for reading!

Edit: Following up with Vuex ORM

I received a lot of feedback on Vuex ORM so I wanted to follow up on why I didn't choose it, check it out here.