championswimmer / vuex-persist

A Vuex plugin to persist the store. (Fully Typescript enabled)
http://championswimmer.in/vuex-persist
MIT License
1.67k stars 116 forks source link

chrome.storage support #251

Open rendomnet opened 2 years ago

rendomnet commented 2 years ago

I'm using vuex for my Chrome extension.

And extensions use special kind of storage.

Chrome storage. It is similiar to localStorage except it is async. https://developer.chrome.com/docs/extensions/reference/storage/

Can vuex work with it?

evanb2 commented 2 years ago

I was having issues trying to get this plugin to work with chrome.storage for my extension so I just rolled my own and it seems to be working well:

import * as types from './mutation-types'

export const chromeStorageSyncPlugin = (store) => {
  // This is just so we know the state path for each mutation
  // we want to listen to since we can't derive it from the `mutation` arg.
  // There may be an easier way to do this, 
  // or you can omit it entirely if you want to sync your entire state tree.
  const STORAGE_MUTATIONS_MAP = {
    [types.SET_SCREEN]: 'currentScreen',
    [types.SET_IS_DRAWER_OPEN]: 'isDrawerOpen',
    [types.INCREMENT_BADGE_COUNT]: 'badgeCount',
    [types.CLEAR_BADGE_COUNT]: 'badgeCount',
    [types.SET_ALERT_SUBSCRIPTIONS]: 'alertSubscriptions',
    [types.TOGGLE_ALERT_SUBSCRIPTION]: 'alertSubscriptions',
    [types.TOGGLE_ALL_ALERT_SUBSCRIPTIONS]: 'alertSubscriptions',
  }

  // Re-hydrate the store on init from storage.
  // I'm toggling this `isLoading` state so I can show a loading screen 
  // to avoid UI blips when the storage data is loaded.
  // Not necessary but you'll probably want to handle this somehow since it's async.
  store.commit({ type: types.SET_IS_LOADING, isLoading: true })
  chrome.storage.sync
    .get([...Object.values(STORAGE_MUTATIONS_MAP)])
    .then((storageData) => {
      store.replaceState({ ...store.state, ...storageData })
    })
    .catch((error) => {
      console.log(error)
    })
    .finally(() => store.commit({ type: types.SET_IS_LOADING, isLoading: false }))

  store.subscribe((mutation, state) => {
    if (Object.keys(STORAGE_MUTATIONS_MAP).includes(mutation.type)) {
      const stateKey = STORAGE_MUTATIONS_MAP[mutation.type]
      // This step is necessary to parse state values,
      // they are stored as Proxys
      const newValue = JSON.parse(JSON.stringify(state[stateKey]))

      chrome.storage.sync.set({ [stateKey]: newValue })
    }
  })
}

// in your store setup...
export default createStore({
  // ...
  plugins: [chromeStorageSyncPlugin]
})

Hope that helps! I literally just wrote this so YMMV 😆

VSKut commented 2 years ago

https://gist.github.com/VSKut/f930eb78755d7ffb5227a4cd327cd7f4

mrleblanc101 commented 1 year ago

Looking at the README and CHANGELOG, it seem like it support async storage and has done so since 0.4.0 in 2017. Did you try it and have problems ? I'm currently building a WebExtension, and I noticed that vuex-persistedstate does not support async storage, but I found this issue through Google.

ArtemZip commented 1 year ago

solved by this https://medium.com/@artemzip/chrome-storage-with-vue-js-in-chrome-extension-ec268a5289d5

mrleblanc101 commented 1 year ago

solved by this https://medium.com/@artemzip/chrome-storage-with-vue-js-in-chrome-extension-ec268a5289d5

I don't pay for medium so I can't