Hello everyone! Today I’ll talk about API requests organisation once again and I’ll raise a little holywar

Most of guides and even frameworks documentations considered as “best practices” told us to go the following way

If you’re on Vue.js and Vuex, you probably often see smth like this:

Official example from Vuex docs

If you’re on React and Redux, you see more variants, but you’ll often see just the wrappers for:

Official example from Redux docs

I bet that most of your Vuex/Redux actions just do API requests and then update state. Isn’t it?

But.. What if I say that it’s just wrong? *somebody closes post right now*

So, what is wrong?

I’ll skip an argument with creating stupid actions that only wrap API requests. It’s a boilerplate code but it’s not a big problem.

Here is only one but critically wrong moment.

Redux/Vuex (underline whatever applicable) is a state management, not API. It should only care about data and its changes but also does API requests handling

Imagine, that we have some store module and we should keep correct state. We have some API that do a part of work for us (adds client token, handles result etc).

I’ll use Vuex for code example. So, we’ll create actions that do API requests and then update our state

Typical store module. Isn’t it?

And then we just call our action and feel OK

But what if I do.. this?..

Ooops!!!

So, there are no updates in state. No info in store actions log. It just happened and your application doesn’t know. And no matter what tool do you use — it’s just a most common architectural mistake.

If you think that docs provide only basic examples to show how %technology_name% works — try to find another examples.

What is an alternative?

My point is —

If you have some API that always have to do something after request, it should be done by API method, not by its wrappers or another application parts

That’s why do we need API layer for that.

Not so far, I published a post about my new library — Apicase. It solves this problem and you don’t need to create your own bicycles. You can read more about Apicase here:

I didn’t want to deep-dive into Apicase here but I think this is the best way to explain and show my idea.

Idea is to write logic that depends on API request inside these requests. In Apicase, you can use it with events + meta. Meta is passed in request with payload. Events are called on request start/progress/done/fail/etc.

So, store action should not call API request, but API request should call store action.

I will write examples based on Vue.js because it’s my favourite frontend framework. So, let’s write some monkey code and then we’ll try to make it simpler.

Step 1. Commit to store

Apicase has 2 nice features to easily realise this idea:

Events that accepts request context

Context has meta option and you can pass whatever you want so it can be used inside events

Services with done events. If we have store — commit some changes to it

Just do request with payload and store passed

Looks better, but still unsafe. We can just do requests without store. So, we’ll throw an error if no store passed.

Step 2. Add some checks

Apicase has two features for that:

Services with unlimited inheritance that allows you split and “stack” payload, meta, hooks etc.

Middlewares (named as “hooks”) that are called before/after request and can modify payload, change response state, abort requests, retry them etc.

I feel safer, ain’t you?

Now we can’t do request without passed store

But it provides tons of boilerplate code. And we are going to step 3!

Step 3. Reduce boilerplate

So, we don’t want to copy-paste events for that. I propose to write commit helper for that:

Move it outside our APIs

And then we can reduce boilerplate code a little:

We also can pass store in tree:

And now update in store is really guaranteed:

Note about API layer

In conclusion I want to say that adding features like this one to Apicase services may make your API layer inseparable from your application. If you want to use the same API layer in different apps, here’s the one more guide:

If you have interesting ideas or questions about Apicase, you can write in replies or mention @apicase on Twitter. Feel free to discuss ;)

Documentation: click here

Github repo: click here

Twitter: click here