How can data be typically encapsulated within Pinia stores when leveraging the composition API?

Currently, in my Vue 3 application with Pinia, I am interested in leveraging the composition API within my Pinia stores. Take a look at this example store:

export const useMyStore = defineStore("my", () => {
    const currentState = ref(0);

    return { currentState };
});

As it stands, I have direct access to modify the value of currentState. However, I'm unsure if this is the best approach or if I ought to consider preventing direct modifications by implementing getter and setter functions like so:

export const useMyStore = defineStore("my", () => {
    const currentState = ref(false);

    const readonlyCurrentState = computed(() => currentState.value);

    function changeState(newState: boolean) {
        currentState.value = newState;
    }

    return { readonlyCurrentState, changeState };
});

In comparison to the options API which offers getters and actions, I find myself questioning whether or not I should follow suit in this scenario.

While the answer may be subjective, I seek insight on whether encapsulating the state currentState would serve to safeguard against accidental corruption.

Answer ā„–1

One can make direct modifications to the value of currentState

Indeed, this intentional choice aligns with Pinia's philosophy, as outlined in the discussion on Vuex comparison

Mutations have been eliminated for being overly verbose. Initially integrated for devtools support, they are no longer necessary.

This intricate decision has sparked debate among developers, as seen in this conversation: Debate over disallowing direct state modification from components

Your example highlights how cumbersome code is required just for simple boolean changes. However, in more complex scenarios where data restrictions matter, uncontrolled mutations may pose risks. Different perspectives on this topic and a possible "strict mode" feature are discussed in the aforementioned thread.

In my opinion, employing linting rules and leveraging TypeScript definitions can enhance safety measures during development without sacrificing runtime efficiency. Pinia grants flexibility in addressing such challenges...

Answer ā„–2

If you find yourself needing to restrict access to data, it is important to note that the second approach may not be the best choice. According to the guidelines provided in the Pinia documentation:

All state properties must be returned in setup stores for Pinia to recognize them as state. This means that private state properties cannot exist within stores.

To address this limitation, the Mastering Pinia blog recommends creating a separate, "private" store that is referenced by the primary store but not directly exposed. To illustrate this concept further:

// The new store is kept internal and not exported
const useMyPrivateStore = defineStore('my-private', () => {
  const currentState = ref(false);

  return { currentState }
})

export const useMyStore = defineStore("my", () => {
    // Nested usage of stores
    const privateState = useMyPrivateStore()

    const readonlyCurrentState = computed(() => privateState.currentState);
    const changeState = (newState: boolean) => privateState.currentState = newState;

    return { readonlyCurrentState, changeState };
  }
);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

String mistakenly interpreted as integer by Django template engine

Here is a sample list: [(2,'09-07-2014')] On the client side, you can access this list using: {% for item in list %} console.log( {{ item.0 }} + ' and ' + {{ item.1 }} ) {% endfor %} The issue arises when item.1 returns -2012, as it ...

Sending form data to a CFC asynchronously in Coldfusion

To begin with, I want to mention that the product I am creating is intended for individuals who do not have automatic access to HTML5. Some of these people are still using IE8. Here's an example of a form: <form action="ee.cfc?method=xlsupload" en ...

What is the best way to add extra plugins to a library that has already been imported through JSPM?

After successfully importing a 3D rendering library with JSPM, I encountered an issue while trying to import the Orbit Controls plugin for Three.js import THREE from 'three.js/build/three'; import OrbitControls from 'three.js/examples/js/ ...

Vue.js/Bueitify: Simplify search results by utilizing the searchable attribute in the b-table component

Currently, I am utilizing the `buefy` framework to develop a table with input filters embedded in columns. Here is a glimpse of the code: <b-table :data="cars" :sticky-header="true" :selected.sync="select ...

How to easily update a URL string in Angular 5 router without altering the state of the application

I am working on an Angular 5 application that utilizes the angular router. The majority of my entry route components are placed under a context id, which represents a name in the app store along with other relevant data for that context. Even though the na ...

Understanding how to use TypeScript modules with system exports in the browser using systemjs

Iā€™m facing an issue while using systemjs. I compiled this code with tsc and exported it: https://github.com/quantumjs/solar-popup/blob/master/package.json#L10 { "compilerOptions": { "module": "system", "target": "es5", "sourceMap": true, ...

Building Dynamic Props in Vue.js using v-select Component

I am utilizing a chart that relies on properties for data. <template> <v-row> <v-col col="12" sm="12"> <Chart :data="series2"></Chart> ### This chart receives the props < ...

Delete the final comma in a JSON file using JavaScript so that it can be utilized by a Vue application

Using Axios in my Vue app, I am consuming a JSON file. The field "country" contains trailing commas which are creating issues. Here is the structure of the JSON: "country": "spain,france," .... "country": " ...

Why State in React Does Not Get Updated When Parent Function is Called from Child Component?

Struggling with getting my child component, ChildButton, to trigger a function in its parent component, ParentTable, that includes a "setState" to refresh or update the table in the parent. I've passed a getData function from the parent to the child ...

Transform the information sent from the server into a user-friendly interface using typescript on the frontend

Received data from the backend looks like this: id: number; user_id: number; car_brand: string; car_model: string; vin: string; equipment: string; reg_number: string; car_mileage: number; car_year: string; Meanwhile, the interface in the ...

Is there a way for me to retrieve and view the specific data that jQGrid is receiving from the controller?

I have a unique attribute that verifies if the user is authenticated. If not, a special JSON string is returned. Therefore, I need to search for that specific string in the data returned from the controller after making a request with jQGrid. How can I ach ...

Using TypeScript with MongoDB aggregation

Recently, I've been working on a User model with the goal of achieving generic aggregation. Essentially, I want to be able to pass an array of objects to a function and have it execute smoothly. Let me provide you with a snippet of the getUser functi ...

Extracting all usernames of members present in a specific voice channel and converting them into a string using Node.js on Discord

Hey everyone, I'm looking for a code snippet that will help me retrieve all the members from a specific voice channel by using its ID. I also need to extract and store the usernames of these members who are currently in that particular voice channel w ...

Transfer photos and videos to an external server using Javascript with Meteor framework

I currently have a meteor application hosted on Digital Ocean. I am considering setting up a dedicated server to store all images and videos separately from the site itself. Whenever a user uploads new media, it will be saved to this separate server. Does ...

Exporting NativeModules for npm package in React Native

I'm attempting to convert my React Native App into a node module. The issue I'm facing is that the module consists mainly of a NativeModule. Thus, my index.js file appears like this: import { NativeModules } from 'react-native'; expo ...

Is there a way to verify the presence of a selector in Puppeteer?

How can I use Puppeteer to check if #idProductType exists and if not, assign producttype to ""? I have tried multiple solutions but none seem to work. const urls = [myurls, ...] const productsList = []; for (let i = 0; i < urls.length; i++) ...

javascript / php - modify input fields according to selection change

Can anyone help me with an issue I'm facing? I want to update multiple textfields whenever a new option is selected from my dropdown menu. I've written the following code, but it's not working as expected. Can someone figure out what's ...

When using ngx-slider in Angular, it unexpectedly fires off when scrolling on mobile devices

I am currently developing a survey application that utilizes ngx-sliders. However, I have encountered an issue on mobile devices where users unintentionally trigger the slider while scrolling through rows of slider questions, resulting in unintended change ...

When a DOM object is passed in JavaScript, its value becomes indeterminate

I am currently working on creating a table that can change its background color based on an RGB value. Each row in this table contains clickable <td> cells that contribute to the RGB value. For example, the first row might be +/- 123, the second row ...

The import failed because 'behavior' is not being exported from 'd3'

I've been experimenting with creating a sankey diagram using d3 and react.js, and I'm using this example as a guide. I am new to React (just 2 days in) and encountering an error that says: ./src/components/SankeyComponent.js An import error occ ...