Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create actions to expose router methods #68

Open
dcherman opened this issue Aug 30, 2017 · 9 comments
Open

Create actions to expose router methods #68

dcherman opened this issue Aug 30, 2017 · 9 comments

Comments

@dcherman
Copy link

Can we consider adding some vuex actions for the following methods:

  • Push
  • Replace
  • Go

Right now, it's a little awkward in that we can access the state from Vuex using this plugin, but you are still required to interact with the router via direct access.

With this proposal, I want the flow to look something akin to this (which I believe is how integrations between react-router and redux generally function):

image

@posva
Copy link
Member

posva commented Aug 30, 2017

Did you know you can import the router and use it:

// actions.js
import router from './router'

export function anAction (context) {
    router.push('/profile/1')
}

@robokozo
Copy link

robokozo commented Sep 21, 2017

So I wanted to do some extra processing on some query params so i wanted to leverage getters to provide the parsed data.

Below:

While i_can_do_this, I think I_prefer_this

var storeConfig = {
	getters: {
		i_can_do_this(state){
			return +state.route.query.thing;
		}
	},
	modules: {
		route: {
			namespaced: true,
			getters: {
				i_prefer_this(state){
					return +state.query.thing;
				}
			}
		}
	}
};

And it works! The sync is probably taking care to merge the route module and the existing route module.

So I also tested this with actions and it's totally fine too.

var storeConfig = {
	modules: {
		route: {
			namespaced: true,
			actions: {
				doSomething(){
					router.push("/something")
				}
			}
		}
	}
};

@alansaldivar87
Copy link

alansaldivar87 commented Oct 12, 2017

I finally found a good solution to use router on actions:
In main.js:

export const router = new VueRouter({
  mode: 'history', 
  routes
})

The constant strictly needs to be exported to use it later on actions.js:

import { router } from '../main'

export default {
   YOUR_ACTION: ({ commit }) => {
      router.push('/goWhereverYouWantTo')
   }
}

@cannap
Copy link

cannap commented May 20, 2018

you can also do

import router from '../router'
Vuex.Store.prototype.router = router

before creating the store
and then in vuex actions you can use this.router.push('/route')

but i have no idea this is good or bad

@isneezy
Copy link

isneezy commented Aug 3, 2018

There is a use case where simple importing import router from '../router' would not work, I'm facing this problem since I'm doing Vue SSR where everything has a factory method!
createRouter, createStore, createApp, etc. This is making it non trivial! It will be very helpful to expose router methods as actions in vuex module.

UPDATE
For now I've done a simple work around to this issue
Changed the sigature of the createStore as follows

// store/index.js
export const createStore = (router) => {
  return new Vuex.Store({
    state: {},
    mutations: {},
    actions: {},
    getters: {
      router: () => router
    },
    modules: {...storeModules}
  })
}

And just use the rootGetters where you what to access $router instance

// store/my-module/actions.js
export const updateOrder = ({rootGetters, getters, dispatch}, order) => {
  const query = getters.params
  query['order'] = order
  rootGetters.router.push({query})
  dispatch('fetchPosts')
}
// store/my-module/getters.js
export const params = (state, getters, rootState) => {
  const params = {}
  params['page'] = state.pagination.page
  params['order'] = rootState.route.query.order
  return params
}

@outkine
Copy link

outkine commented Sep 19, 2018

@cannap's solution seems to work quite well - I think it's the superior choice because it is significantly more generalized, and you don't have to add any extra code.

@isneezy
Copy link

isneezy commented Sep 19, 2018

@outkine the problem with the @cannap solution is that you are changing the Vuex.Store node module prototype (its a kind of static variable), so if you need to instantiate your store twice or more you'll get the same router on every vuex store instances. Since VueSSR is a long running process each request should have their own instance of Vue, Vuex, VueRouter, and so on. Making that solution not viable.
Sorry about my bad English.

@outkine
Copy link

outkine commented Sep 20, 2018

That definitely makes sense, and is probably the best long-term solution. In my case I was just looking for a quick patch, as I don't have SSR.

@isneezy
Copy link

isneezy commented Nov 19, 2018

Is there any update on this? I can work on this issue/feature if the maintainers agree to, I can not waste time on something useless that will be discarded and not merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants