# No  more Load/Store use StorageLike

## Motivation

The typical Pinia tutorial tells you to write a Load and Store function to manage, well loading and storing your state from and to the server. I have never seen a single one of them mention this approach, they all are some variation of the `load`() function called in `onMounted()`.

I think that is a complete disservice to new users just discovering Pinia as for the majority of cases, it is not the easiest or simplest solution to be teaching those new to Pinia, and probably Vue as well.

There is a better way for the majority of use cases using the [PersistedState](https://prazdevs.github.io/pinia-plugin-persistedstate/) plugin.

This plugin provides for configurable persistence of Pinia stores, and provides support for Session, LocalStorage and Cookie persistence out of the box.

It is trivial to provide custom persistence if you design your API calls in a consistent manner.

There are plenty of articles and tutorials on how to use [pinia-plugin-persistedstate](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts), so I am not going to go into how to use it, but instead explain how to design your remote api so making using it is simple and secure as possible.

## StorageLike

The main thing to know about this plugin is the following Interface, this is what you implement to allow the plugin to do its magic and relieve you of all the boilerplate error prone stuff it does.

```typescript
/**
 * Synchronous storage based on Web Storage API.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
 */
export interface StorageLike {
  /**
   * Get a key's value if it exists.
   */
  getItem: (key: string) => string | null

  /**
   * Set a key with a value, or update it if it exists.
   */
  setItem: (key: string, value: string) => void
}
```

This is what you want your remote api to look like as well, sort of.

Lets say you have a `User` and you want to load the current `User` after they authenticate. Here is what you should make your remote API look like.

I am going to use an actual [REST](https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf)ful API over HTTP, because that is what most people will be familiar with and it illustrates the approach the simplest way possible.

```http
GET /user
PUT /user
```

## GET /user

For security you should make these routes require authentication and enforce it in “middleware” or whatever your server calls request pre-processing interceptors.

You already know who the user is, so you do not need to pass in an `id` to either call. This is the most secure. It is also the simplest way to write the client and server code as well. The request handler is protected and should never receive anything that is not authenticated, and will get the user id to find and return as data that the authentication handler provides.

## PUT /user

contrary to what every TODO app tutorial you and whatever chat “ai” code generator you are using tells you, the `PUT` verb is NOT just for creation of resources.

As per the [official documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT);

> The `PUT` HTTP method creates a new resource or replaces a representation of the target resource with the request [content](https://developer.mozilla.org/en-US/docs/Glossary/HTTP_Content).

semantically, you should use `PUT` for creating and updating resources when you are providing the entire resource. And if you are doing REST, you are providing the entire resource, right? RIGHT?

This is the most efficient way to updating the remote state, providing the entire resource, and is the entire point behind the [REST](https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf) approach. [REST](https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf) stands for [**Representational State Transfer**](https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf), if you are not transferring state you are not doing REST**.** This example is a REST example so we are doing REST.

If you need to do partial updates to a resource for some reason, then `PATCH` is the correct way to do it, **not** `POST`! There may be reasons to do a partial update of a resource, but almost always they should because of some side effect of the business logic on the server side.

The only reasons to submit partial resource updates to the server are functional;

* you do not have the entire resource to submit with the updated part.
    

* the entire resource is large and it would be inefficient to transmit such a large payload just to change a very small percentage of the data.
    
* Whatever you are updating will cause some kind of side-effect on the system receiving the update that is not idempotent.
    

Partial updates by definition are not RESTful. They are basically [RPC](https://datatracker.ietf.org/doc/html/rfc1050) calls over HTTP. To be pedantic, I know they are not Remote Procedure Calls, but in they are remote calls to a procedure, and they are over HTTP, so semantically they are a form of [RPC](https://datatracker.ietf.org/doc/html/rfc1050). *Unless, the partial update is treated as a resource, and then it should be transmitted via* `PUT`. This gets into a kind of recursive rabbit hole quickly.

## PATCH /user

> The `PATCH` HTTP method applies partial modifications to a resource.
> 
> In comparison with `PUT`, a `PATCH` serves as a set of instructions for modifying a resource, whereas `PUT` represents a complete replacement of the resource.
> 
> A `PUT` request is always idempotent (repeating the same request multiple times results in the resource remaining in the same state), whereas a `PATCH` request may not always be idempotent.

`PATCH` is not the correct choice to use for implementing your [StorageLike](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts) server side implementation.

## POST /user

> The `POST` HTTP method sends data to the server.
> 
> The difference between `PUT` and `POST` is that `PUT` is idempotent: calling it once is no different from calling it several times successively (there are no side effects). Successive identical `POST` requests may have additional effects, such as creating the same order several times.

`POST` is not the correct choice to use for implementing your [StorageLike](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts) server side implementation.

## DELETE /user

There is no `DELETE` in the StorageLike interface, I am not sure how I feel about this, given how I feel about `null`. There will be a temptation for a lot of you that do not know better to implement `DELETE` by just setting the store state to `null` or whatever you want to `DELETE` to `null` and handle that as a special case in the `setItem(key,value)` function. Resist this urge! It will just lead to suffering.

A better approach would be to do your `DELETE` explicitly. Click button, call `DELETE` and then update the store state to reflect the server state. The client state should always represent the server state, not the other way around. This eliminates entire classes of bugs and will save you time in the long run.

If at some point in the future, you find out from profiling that you need to make it more efficient, then do that, but initially, stay as close to *client represents server state* as possible. The easiest way to do that is to mutate the server state and then sync the client state to match the server.

## Conclusion

As I stated in already, I wrote this up because this approach is not the mainstream approach to using Pinia and I think it should be. This is my attempt to add to the information that might be found be people new to Pinia and trying to figure out how to best leverage it.
