GithubHelp home page GithubHelp logo

vuex-electron's Introduction

Vuex Electron

Travis Code Climate Code Climate Code Style Prettier Made With Love

The easiest way to share your Vuex Store between all processes (including main).

Features

⭐ Persisted state
⭐ Shared mutations

Requirements

Installation

Installation of the Vuex Electron easy as 1-2-3.

  1. Install package with using of yarn or npm:

    yarn add vuex-electron
    

    or

    npm install vuex-electron
    
  2. Include plugins in your Vuex store::

    import Vue from "vue"
    import Vuex from "vuex"
    
    import { createPersistedState, createSharedMutations } from "vuex-electron"
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      // ...
      plugins: [
        createPersistedState(),
        createSharedMutations()
      ],
      // ...
    })
  3. In case if you enabled createSharedMutations() plugin you need to create an instance of store in the main process. To do it just add this line into your main process (for example src/main.js):

    import './path/to/your/store'
  4. Well done you did it! The last step is to add the star to this repo 😄

Usage example: Vuex Electron Example

IMPORTANT

In renderer process to call actions you need to use dispatch or mapActions. Don't use commit because actions fired via commit will not be shared between processes.

Options

Available options for createPersistedState()

createPersistedState({
  whitelist: ["whitelistedMutation", "anotherWhitelistedMutation"],

  // or

  whitelist: (mutation) => {
    return true
  },

  // or

  blacklist: ["ignoredMutation", "anotherIgnoredMutation"],

  // or

  blacklist: (mutation) => {
    return true
  }
})

Author

Andrew Emelianenko
IG: @truemelianenko

License

MIT License

vuex-electron's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vuex-electron's Issues

Bump deepmerge

WhatsApp Image 2020-01-24 at 09 38 49

I have a problem that I think can be solved by upgrading the deepmerge package.
I can't start a workspace in my machine, something with python2 and node-gyp, so I don't open a PR.

Failed to serialize arguments

Hello, I am very new to electron, vue and Vuex. Currently I am running into an issue after I updated my MacOS of "failed to serialize arguments":

Screen Shot 2020-10-12 at 4 35 27 PM

Currently my tech stack for this project is Vue.js, Electron and Spring Boot.

If anyone could point me in the right direction of what may be happening or what I should be looking for It would be greatly appreciated.

Thank you

Is Data Stored in my Vuex when i build electron app and then close it?

Hey Guys i'm so confusing i want to build an electron app whit vue an vuex i have two questions

  1. if i close app (for example turn off my pc and after few days turn on it and open the app again ) , all data saved to vuex or not ? need i use databases like sqlite to store data from vuex?

  2. i want to have two databases localdatabase and online database i can handle online database but how can i share some localdatabase to server for example i add two project to my local database and i want send second projects'data with axios to server how can i handle this i should to have sqlite-vuex-vue-electron or i can handle it with vuex-vue-electron

Dispatch not being fired from component

I am having an issue with attempting to dispatch an action within a component. It seems that the dispatch is not being received by the store action.

However, if I change the setter to use this.$store.originalDispatch() it works fine.

It appears that notifyMain in shared-mutations.js is not working. What am I missing here?

(FYI: I am using Nuxt, so access to the store is via this.$store.)

In my template I have:

<v-text-field
  slot="activator"
  v-model="sample"
  label="Sample store test"
  hint="Is it working???"
></v-text-field>

The setter and getter I have defined as:

  computed: {
    sample: {
      get: function() {
        return this.$store.state.sample;
      },
      set: function(val) {
        this.$store.dispatch("updateSample", { value: val });
      }
    }
  },

The updateSample never gets fired in my store:

state: {
	sample: 'Hey there!'
},
plugins: [ createPersistedState(), createSharedMutations() ],
getters: {},
mutations: {
	setSample(state, val) {
		debugger;
		state.sample = val;
	}
},
actions: {
	updateSample(store, payload) {
		debugger;
		store.commit('setSample', payload.value);
	}
},

Type error if using vue-cli without proper webpack config

You may want to consider updating the readme to cover an error I was running into. Even though it's not caused by this package, it may be helpful for troubleshooting.

I had bootstrapped my project with vue-cli and was seeing this error after adding the createPersistedState to my store:

TypeError: fs.existsSync is not a function at getElectronPath

I believe this is caused by referencing electron outside of the main.js file.

I fixed it by adding this to my vue.config.js in order to set my target properly:

configureWebpack: config => {
  config.target = "electron-renderer";
}

Could not find a declaration file

I imported the module like this
import { createPersistedState, createSharedMutations } from "vuex-electron"

and got the error:

5:61 Could not find a declaration file for module 'vuex-electron'. 'C:/Users/pasca/Projects/time-manager/node_modules/vuex-electron/dist/index.js' implicitly has an 'any' type.
  Try `npm install @types/vuex-electron` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuex-electron';`

I kinda fixed it with adding a index.d.ts file in the modules containing declare module 'vuex-electron'; but im getting a
Module not found: Error: Can't resolve 'worker_threads' in 'C:\Users\pasca\Projects\time-manager\node_modules\write-file-atomic' error now

dispatch

Loop call(dispatch) updata window inside vuex error:EPERM:operation not permitted, rename

Not updating the state

If I use both createPersistedState, createSharedMutations I can call store.dispatch('setAuthCode', query.code ) from my main process.

If I remove createSharedMutations I can not.

But using both, I can not update the state in my component using: this.$store.dispatch('setAuthCode', code)

If I remove createSharedMutations I can update state in my component.

Without createSharedMutations the vuex.json updates, but it is not reacting and updating in the component.

How can I call an action to mutate the state from both main and render process? I thought this was the point of the package. Not either or.

What gives?

[fix] [Vuex Electron] Storage is not valid. Please, read the docs.

I got a fix for you guys. I struggled with that for my application on my windows users and it is really annoying.
However, I've found a valide workarround.

The error and crash happens due the thrown error in the plugin.
So you 2 options. Either you fix the race condition or you handle the Storage creation properly.

I am using 4 windows on my side and all of them have parallel access to the storage which makes everything complicated but however I could get it running without hassle once I put the creation in a while loop.

function createStore(){
    return new Vuex.Store({
      plugins: [
        pathify.plugin,
        createPersistedState({
          throttle: 1000,
          whitelist: (mutation) => true,
        }),
        createSharedMutations()
      ],
      modules
    })
}

let store

while(store === undefined){
  try {
      store = createStore()
      break;
  }
  catch(e){
      // alert("Error in Store, guess race condition. Recreating Storage." + e)
      continue;
  }
}

export default store

actions get surpressed without any log message

...mapActions({
        addPod: 'pods/add',
        updatePod: 'pods/update',
        removePod: 'pods/remove',
        resetPods: 'pods/reset'
      })

i'm calling the addPod Action but my action never gets hit.. if i remove this plugin from vuex it works seemless.

Please let me know if i can provide more data.

my vuex index.js

import Vue from 'vue'
import Vuex from 'vuex'

import modules from './modules'
import {createPersistedState, createSharedMutations} from 'vuex-electron'

Vue.use(Vuex)

export default new Vuex.Store({
  modules,
  strict: process.env.NODE_ENV !== 'production',
  plugins: [
    createPersistedState({
      whitelist: ['setCurrentNamespace']
    }),
    createSharedMutations()
  ]
})

Maintainers required

Hi guys,

I'm not able to allocate a lot of time for this project anymore. So I'm looking for a good developer who can help me. I'll give him access to the repository, so he'll be able to merge pull-requests and release updates.

Requirements:

  • 3+ years experience in JavaScript
  • An open-source repo with 100+ stars (optional)

Have a good day,
Andrew

access state in main process

I'm using this package within the electron-vue boilerplate template.

my module looks like this:(pathsData.js)

const state = {
  filePath: 'test',
  framesFolderPath: '',
}

export default {
  state
}

my main process js file starts with:

import store from '../renderer/store'
console.log(store.state.pathsData)

the output this console.log is:
{ filePath: [Getter/Setter], framesFolderPath: [Getter/Setter] }

when I try to log filePath with:

console.log(store.state.pathsData.filePath)

I expect the string test but nothing will be logged in the console

How to save and edit arrays in Store?

I have this structure of Settings model
const state = { price_between: { enabled: false, value: [0,0] } }
Then change the value to [10, 10] via mutation;
state['price_between'].value = [10, 10]; and it works fine, and i get this array as expected.

But now i refresh page and get state:
state.price_between === [0, 0, 10, 10];

And every time i reload page, it just adding new values in array; I never use .push() or something. Always changing like value[0] = 10;

Feature: Add get/set mapping to store fields.

One of the missing capabilities of Vuex is the ability to do two-way v-model binding directly from the store object (you have to write your own setter and getter for each store object). If your form is extensive, that is a lot of unnecessary coding.

One solution I use in standard (non-electron) vue applications is vuex-map-fields. It allows you to bind to a store field directly with v-model when you just need a simple set/get.

Your computed v-model-friendly property becomes:

    computed: {
      ...mapFields([
        'firstName',
        'lastName',
        'email',
        'phone',
        'address1',
        'address2',
        'city',
        'state',
        'zipcode'
      ]),

It would be VERY handy to have this same capability (using dispatch) built into vuex-electron. 😃

Webpack 5 incompatibility

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case.

Uncaught Error: [Vuex Electron] Storage is not valid. Please, read the docs.

Hi, Integrate the vuex into the electron , my application will run to this issues,

Uncaught Error: [Vuex Electron] Storage is not valid. Please, read the docs.
at a (C:\Users\Administrator\Desktop\win-unpacked\resources\app.asar\node_modules\vuex-electron\dist\persisted-state.js:1)
at C:\Users\Administrator\Desktop\win-unpacked\resources\app.asar\node_modules\vuex-electron\dist\persisted-state.js:1
at C:\Users\Administrator\Desktop\win-unpacked\resources\app.asar\node_modules\vuex\dist\vuex.common.js:345
at Array.forEach ()
at new Store (C:\Users\Administrator\Desktop\win-unpacked\resources\app.asar\node_modules\vuex\dist\vuex.common.js:345)
at Object. (renderer.js:1)
at d (renderer.js:1)
at n (renderer.js:1)
at Object. (renderer.js:1)
at d (renderer.js:1)

Who knows going on with this? I confusion with this problem about on week;

blacklist functionality broken?

First, let's look at what is working as expected:

createPersistedState({
  blacklist: (mutation) => {
    return true
  }
})

This will never persist any state. However, this is a bit pointless as the same result could be achieved by not using the createPersistedState plugin at all.

Now let's look at the case when blacklisting certain mutations, by providing a list of mutations:

createPersistedState({
  blacklist: ["ignoredMutation"],
})

Well, it's true that the state is not persisted when ignoredMutation is fired. However, the whole state will be persisted the next time a non-blacklisted mutation is triggered - which includes all the previous mutations, even the blacklisted ones. Basically you're only delaying persistence that way but not blacklisting it.

So the question is: Is this implemented as designed? If yes, where's the point in that?
The only use I can imagine is that it allows you to blacklist certain mutations for performance reasons (e.g. in case they are triggered that often that you don't want to write to the persistence file every time). But I doubt that this is what users would expect based on the limited documentation.

vuex-electron doesn't support batch deleting by condition from vuex-orm

createSharedMutations doesn't allow to work with batch deleting method by condition from vuex-orm, which has the following form:

The issue with the loop of the method File.delete((file) =>... (with the condition)
But other methods work well (insert, update, find, etc.).
Also File.delete(id) without the condition works well.

In vuex-orm, both deleting by id and deleting by condition run the same mutation code. I cannot tell you why one works and the other doesn’t but I suspect it may be related to createSharedMutations. When I hide createSharedMutations() plugin (vuex-electron), the batch deleting method will work (I see the loop by the condition is starting work), but in vuex.json file won't be any changes.

the related link: vuex-orm/vuex-orm#621

How to rehydrate after restarting or reloading.

This is more of a question as I cant find any information on it or dont know what im looking for, I have a basic app. Im wanting to know how to rehydrate the state after the application is restarted or closed.

my store is using the following:

plugins: [
    createPersistedState(),
    createSharedMutations(),
  ],

and my main is importing the store but when the application reboots the store is blank again.

Remove "don't use direct commit's" trap

Hi there,

Thanks for the lib. It seems from the source code there is a lot to do to get Vuex working nicely with Electron!

One thing I think is too much though, is the trap to prevent commits outside of stores:

https://github.com/vue-electron/vuex-electron/blob/master/src/shared-mutations.js#L54-L56

Surely it's not this library's place to decide on individual developer preference. Committing outside of actions is perfectly valid, especially for those who choose not to tightly couple their API to Vuex (like me!).

Can this be removed please?

caching data In nuxt js , vue

how can i cache my data in nuxt js , for example when a user come and see my posts and then after few days he/she sees my website again can i use catch for retrieving data ? and dont use ajax again for get api's data ?‌ and what happened when i add new post‌? will data update itself and get just new data ?

Prototype and functions not maintained in the process it was created

The problem

I use this library in a project where i store a class in my state, kind of like this:

class MyCount {
  var count = 0

  getCurrentCount() {
     return count
  }
}

export default new Vuex.Store({
  state: {
    myCount: new MyCount()
  },

  actions: {
    newCounter(store, payload) {
      store.commit("newCounter", payload)
    }
  },

  mutations: {
    newCounter(state, payload) {
      state.myCount = payload
    }
  },

  plugins: [createPersistedState(), createSharedMutations()],
  strict: process.env.NODE_ENV !== "production"
})

Now this is an oversimplified example. In my case it's not really a class, but an object that has functions added to it by a 3rd party library.

The problem is that when i dispatch the newCounter action from a renderer process the action is being intercepted and processed on the main process instead.
For this to happen, you currently send the dispatch type and payload using ipcRenderer.send(), which results in the payload losing the prototype chain and all functions as stated in the docs.

Proposed solution

I tried modifying the code of sharedMutations.js locally to simply sync mutations both ways instead of broadcasting them from main.
The result is that the prototypes and functions will be available within the process they were created, which i feel makes more sense than having all prototypes in the main process.
It seems to work well for my application, but I'm curious to whether or not you see an issue with this implementation.

I also removed the restriction of having to use actions in the renderer process, any mutations are now synced both ways.

rendererProcessLogic() {
  // Connect renderer to main process
  this.connect()

  var mainMutating = false

  // Subscribe on changes from main process and apply them
  this.onNotifyRenderers((event, { type, payload }) => {
    mainMutating = true
    this.store.commit(type, payload)
    mainMutating = false
  })

  // Subscribe on changes from Vuex store
  this.store.subscribe(mutation => {
    if (!mainMutating) {
      const { type, payload } = mutation

      // Forward changes to renderer processes
      this.notifyMain({ type, payload })
    }
  })
}

mainProcessLogic() {
  const connections = {}

  // Save new connection
  this.onConnect(event => {
    const win = event.sender
    const winId = win.id

    connections[winId] = win

    // Remove connection when window is closed
    win.on('destroyed', () => {
      delete connections[winId]
    })
  })

  // Subscribe on changes from renderer processes
  this.onNotifyMain((event, { type, payload }) => {
    const win = event.sender
    const winId = win.id
    delete connections[winId]
    this.store.commit(type, payload)
    connections[winId] = win
  })

  // Subscribe on changes from Vuex store
  this.store.subscribe(mutation => {
    if (connections) {
      const { type, payload } = mutation

      // Forward changes to renderer processes

      this.notifyRenderers(connections, { type, payload })
    }
  })
}

I am willing to set up a PR if this is something you would like to use.

Locally stored state doesn't get updated and causes weird merges

I'm writing this mostly as a warning, as I lost hours debugging this...
(I'm using the base Vue Electron boilerplate from CLI3.)

My project started with a store.js file, I converted it to a folder with an index.js and a vuex module for better organization.

I imported the store to my electron's main process file (background.js) and console.log to see that the state from my old and deleted store.js is still present in the main process. One of my modules has the same name as one of the old properties, so that's causing issues..

I assume this all has something to do with electron-store saving the store locally, but this can't be the intended use... can it?

EDIT: Well I seem to have a thing for solving my own problems the second I open an issue, it was indeed due to the vuex.json file in my app's userData folder.. I did further tests and found out that changing my vuex state in any way while developing didn't change the local version. I dont know if this is intended, but I can't work with inconsistencies like this.. Hope I saved someone some time :)

handle error in dispatch

how to handle error in dispatch ? i want build promise in dispatch but error trigger in main process how to handle in renderer process ?

How to return promise from an action?

In all my projects with vuex I used to call api methods in module's actions, store result in state and then handle result in component method by returning Promise like this:

Component:

{  
  methods: {
    ...mapActions([
      'loadPages'
    ]),
    handleLoad () {
      this.loadPages().then(() => this.$router.push({ name: 'pages' }))
    }
}

Vuex module:

import { load } from '@/api/pages'

const state = {
  pages: []
}

const mutations = {
  LOAD_PAGES (state, pages) {
    state.pages = pages
  }
}

const actions = {
  storeAuthor ({commit}, items) {
    return load().then(pages => commit('LOAD_PAGES', pages))
  }
}

export default {
  state,
  mutations,
  actions
}

It seems like using vuex-electron and createSharedMutations I can't do this anymore, since vuex actions now return undefined.

So how to handle when action was accomplished?

[shared data] Master init failed

I don't want use createPersistedState() plugin,i remove it,but is having a wrong like this

[17276:1015/164137.107:ERROR:CONSOLE(7)] "[shared data] Master init failed", source: chrome-extension://vue-js-devtools/build/devtools.js (7)

it print all the time
image

state return previous data after page refresh

//store.js
import Vue from 'vue';
import Vuex from 'vuex';
import { createSharedMutations } from 'vuex-electron';
import AddresseStore from './Address.store';
Vue.use(Vuex);
export default new Vuex.Store({
  modules: {

    address: AddresseStore,
  },
  actions: {
    init() {},
  },
  plugins: [createSharedMutations()],
//   strict: process.env.NODE_ENV !== 'production',
});
//Address.store.js
export default{
state: {
    countryList:[],
},
getters:{
countryList(state){
return state.countryList
}
},
mutations:{
SET_COUNTRY_LIST(state,payload){

console.log(state.countryList);   
//------------PROBLEM---------------------
//=>first load: [] 
//=>after refresh page ['ITALY','SPAIN']  (don't want this behavior i want my state initial value which is []  because i'm reloading page)
//------------------------------------------------
state.countryList =payload;
}
},
actions:{
loadCountryList(context){
axios.get('localhost:3000/country-list').then((result)=>{
context.dispatch('SET_COUNTRY_LIST',result);
})
}
}
}
//address.component.vue
<template>
<section>
<div v-for="(country, index) in countryList" v-bind:key="index">
{{country}}
</div>
</section>
</template>
<script>
export default {
  name: 'AddressComponenet',
computed:{
countryList(){
return this.$store.getters['address/countryList'];
}
},
mounted(){
this.$store.dispatch('address/loadCountryList');
}
}
</script>

after page refresh store giveback previous data stored.
how can i prevent store from keeping data?

Can't resolve '@/components/...' when importing router into Vuex module file

Hey guys,I have the same problem with this. SimulatedGREG/electron-vue#758

The documentation is still not clear enough, such as the parameters in the whitelist are too general.

In my application, vuex contains app, user, win 3 modules. In the main I only use win, the other 2 are used in the renderer, how can I set createPersistedState()

`createPersistedState({
whitelist: ["whitelistedMutation", "anotherWhitelistedMutation"],

// or

whitelist: (mutation) => {
return true
},

// or

blacklist: ["ignoredMutation", "anotherIgnoredMutation"],

// or

blacklist: (mutation) => {
return true
}
})`

Help me answer if you have time, thank you

No console or network logged

Hey guys

I’m using this neat module for my electron app but I can’t see any console log or network request when sending it from my store.

If I move the same method to the vue instance it works just fine.

It does send the request etc within the store but it’s impossible to see the console or request in the console of the renderer or even the command line.

I did import the store in the main and the renderer processes.

Any idea if I’m doing something wrong?

thanks

bad file descriptor errors

I keep getting errors, Uncaught Error: EBADF: bad file descriptor, close, that point back to the setState function in PersistedState.

I wonder if this happens when multiple mutations happen in quick succession. Is there a known limitation in this sense? Is so, might it be possible to implement some kind of debounce to prevent file issues?

Example project?

This appears to be the holy grail 😮 (sharing of store between processes) but the lack of example code leaves me wondering how it works. How do you access store data and fire actions from the main process? I'd love to know if anyone has any example code online?

Q: Is there any particular caveats to change persistance library?

I was considering changing my vuex persistence package, since the blacklist feature (which I badly need) is currently broken.
I would just like to know of any suggestions as to which alternate package to use, as well as anything I should look out for etc.

Thanks.

Persist partial state

The whole global state is persisted in the Store: https://github.com/vue-electron/vuex-electron/blob/master/src/persisted-state.js#L96

It would be nice to be able to only save parts of the state. We can easily imagine that some part of the state are transient (only relevant to the current execution of the application) and shouldn't not be persisted on disk (and not reloaded at startup).

On top of my mind changing setState like this could be sufficient:

setState(state) {
        const stateToPersist = typeof this.options.statePick === 'function' ? this.options.statePick(state) : state
        this.options.storage.set(this.options.storageKey, stateToPersist)
}

And because the loading operation do a deep merge with the initial state it should work seamlessly. Thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.