Navigating through different views in a Vue application using Vue Router directly from Vuex actions

Currently, I am in the process of developing a web application using Vue 2.x and Vuex 2.x. In this project, I need to retrieve some data from an external source via an http call. If this call fails, my objective is to redirect to a different page.

GET_PETS: (state) => {
  return $http.get('pets/').then((response)=>{
      state.commit('SET_PETS', response.data)
    })
  },
  error => {this.$router.push({path:"/"}) }
  )
}

However, when attempting this.$router.push({path:"/"}), an error is thrown as follows:

Uncaught (in promise) TypeError: Cannot read property 'push' of undefined

I am seeking advice on how to accomplish this task effectively.

For a simulated example, check out this JsFiddle: here

Answer №1

If you have your router instance exported in a file within your app (for example, ./router.js), you can easily import it and use it anywhere you need - even in Vuex stores:

import router from './router';

Once imported, you can simply call router.push().

It's as straightforward as that.

Answer №2

This demonstration could be beneficial.

main.js

import Vue from "vue";
import VueRouter from "vue-router";

...

Vue.use(VueRouter);

export const routing = new VueRouter({
    mode: 'hash',
    base: "./",
    routes: [
        { path: "/", component: welcome},
        { path: "/welcome", component: welcome},

    ]
})

actions.js

import {routing} from "../main.js"

export const performAction = ({commit}) => {

    routing.push("/welcome");
} 

Answer №3

STARTING POINT

Within the file main.js (the one where all modules are installed and a Vue instance is created, like in src/main.js):

const vm = new Vue({
  el: '#app',
  router,
  store,
  apolloProvider,
  components: { App },
  template: '<App/>'
})

export { vm }

This serves as an example, with focus on const vm and router in our context.

In your store:

import { vm } from '@/main'

yourMutation (state, someRouteName) {
  vm.$router.push({name: someRouteName})
}

P.S. By using import { vm } from '@/main', we gain access to necessary elements in Vuex like vm.$root required by certain components of bootstrap-vue.

P.P.S. It's important to note that we can utilize vm only when everything is fully loaded. In simpler terms, cannot use vm inside someMutation if called within mounted() because mounted() occurs prior to the creation of vm.


FRESH PERSPECTIVE

Constantin's response (the accepted one) as explained here is more effective than mine, aimed at guiding beginners on its implementation.

Within the core directory (located in /src for me), alongside files like App.vue and main.js, I have a file named router.js structured as follows:

import Vue from 'vue'
import Router from 'vue-router'

// Traditional loading
import Home from '@/components/pages/Home/TheHome'

// Lazy loading (loaded when corresponding route is accessed)
const Page404 = () => import(/* webpackChunkName: "Page404" */ '@/components/pages/404)
const Page503 = () => import(/* webpackChunkName: "Page503" */ '@/components/pages/503)

Vue.use(Router)

const router = new Router({
  mode: 'hash',
  base: process.env.BASE_URL,
  linkExactActiveClass: 'active',
  routes: [
    {
      path: '*',
      name: 'Page404',
      component: Page404
    },

    {
      path: '*',
      name: 'Page503',
      component: Page503
    },

    {
      path: '/',
      name: 'Home',
      component: Home
    },

    // Additional routes
    {....},
    {....}
  ]
})

// Universal section allowing actions before entering a new route.
router.beforeEach(async (to, from, next) => {
  next()
})

export default router

Include our router in main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

const vm = new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

export { vm }

Lastly, be it within a component, Vuex, or any other place, remember to import router from './router' and proceed accordingly, such as invoking router.push(...)

Answer №4

It appears that the router is not properly integrated into your app, leading to it being undefined.

In older versions of vue-router, you would need to use Vue.use(VueRouter). However, with version 2.0, you can inject the router into the app in the following way:

const routes = [
  { path: '/foo', component: Foo },
]

const router = new VueRouter({
  routes
})

const app = new Vue({
  router // inject the router
}).$mount('#app')

This should allow you to access the router throughout the entire app using this.$router


After addressing a similar question on Stack Overflow: How to use Vue Router from Vuex state?, it became evident that Vuex does not automatically receive the router instance at this.$router. As a solution, two methods were proposed to gain access to the router instance.

The first method is more straightforward and involves setting a webpack global variable to the instance.

The second method suggests using Promises within your Vuex actions, allowing components to access the router instance after the Promise is resolved or rejected.

Answer №5

I found it cumbersome to maintain my app's location state separately from the main app state in the Store, along with managing both a Router and a Store simultaneously. To simplify this process, I decided to develop a Vuex module that handles the location state within the Store itself.

With this setup, I am now able to navigate through dispatching actions, just like any other state change:

dispatch("router/push", {path: "/error"})

This approach also streamlines tasks like managing animated page transitions.

Creating your own router module is straightforward, but you may also consider using mine if you prefer:

https://github.com/geekytime/vuex-router

Answer №6

To import the route from the router directory, you can use the following code snippet:

import router from '@/router'

router.push({name: 'Home'})

The @ symbol serves as a shortcut for referencing the path to the src directory.

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

Click on any checkbox to select all checkboxes at once

I have created a table with each column containing a checkbox. My goal is to select all checkboxes in the table when I click on the checkbox in the top row (th). Can someone guide me on how to achieve this? Below is my code: <table style="width:100%"& ...

Writing the success function for a jQuery ajax call involves defining the actions to be taken once

Embarking on my journey to learn jQuery and web development, I am faced with the task of sending user input (username and password through a submit button) to a PHP page using .ajax and success function. Below is the HTML form code: <form id="form1"&g ...

What is the method to disable response validation for image endpoints in Swagger API?

I'm working with a Swagger YAML function that looks like this: /acitem/image: x-swagger-router-controller: image_send get: description: Returns 'image' to the caller operationId: imageSend parameters: ...

The $geoNear operator must be the initial stage in a pipeline to be valid

When performing an aggregation using nodejs as the server-side language, I encountered the error message $geoNear is only valid as the first stage in a pipeline. This is the Aggregation Object: [ { '$geoNear': { near: [Object], distanceFie ...

Guide for accessing and interpreting a random folder arrangement using JavaScript located alongside index.html

I am currently developing a testing reporting tool that organizes images into folders, resulting in a structure similar to this: root/ /counter/ img1.png img2.png /alarm/ img3.png The names of the folders like counter and alarm are not f ...

I am encountering a problem while performing JavaScript validations

In jQuery or using the element's ID, I can validate a textbox. For example: var field = document.getElementById('tbxSearchField').value if (field == "") {alert("please enter text");} The HTML code is as follows: <input class="input" id ...

Is it possible to create a function that executes if a checkbox is checked, and another function if

When the radio button with the ID m1 is checked, my mesh updates its position. I attempted to make the mesh return to its original position if "#m1" is no longer checked. Is it necessary to trigger a function when checked and a different function when no ...

Using AJAX in a WordPress template

I'm currently facing an issue with integrating my operational php/javascript/ajax application into my WordPress theme. This application is meant for my users and not within the admin panel. Steps I've taken: I have successfully included the Java ...

How can a false validation be conducted on knockout js?

Using knockout js, I have an input type checkbox and I want to trigger the "not true" action when this checkbox is selected. Here's what I have attempted: <input type="checkbox" data-bind="checked: !IsVisible"/> Unfortunately, this code isn&ap ...

The length of the scope variable generates an error

var example = $scope.newgoal.gTitle; console.log(example.length); Even running this short code test, it throws an error message: TypeError: Cannot read property 'length' of undefined I've attempted to find various solutions without succes ...

Creating a module within a component in angular - step by step guide

I am interested in dynamically creating a component inside another component. This will allow me to pass my dynamic HTML template directly to the decorator like this: //code /** * @param template is the HTML template * @param container is @ViewChild(& ...

Rails 4 does not properly handle the execution of Ajax responses

Currently, I am incorporating ajax functionality within my Rails application. Within the JavaScript file of my application, the following code snippet is present: $('#request_name').on('focusout', function () { var clientName ...

Encountered a SyntaxError while deploying Nuxt.js SSR on Passenger: The import statement cannot be used outside a module

I am currently in the process of deploying my Nuxt app on a hosting service that uses Passenger to run Node.js applications. After building the app with the command ">npm run build" and deploying the content from the .nuxt folder onto the server, specif ...

Issue with isNan() and typeof in React framework

I'm attempting to create a field in the react-bootstrap component that only accepts numeric input. I know there is a type="number" attribute that can be used, but it's currently set to password to mask the input. Initially, I tried this approach ...

The AJAX success callback function failed to execute in cases where the dataType was set to JSONP during Cross domain Access

type = 'math'; var ajurl = "sample.com&callback=myhandler"; var datas = "cateid=" + cateid + "&type=" + type + "&pno=" + pno + "&whos=" + whos; $.ajax({ type: "GET", url: ajurl, data: datas, contentType: "application/json; ...

Utilize Vuex to streamline and organize multiple requests within a group

Our current Vue + Vuex application is designed with numerous custom components on each page, all connected to MongoDB as our database. Every component fetches data from an API endpoint on initialization: async loadData() { const data = await getData(&a ...

Different ways to modify the color of a chart using am4chart

I am using am4chart to create a line chart on my website. The background of the website is black, so I need to make the chart white. https://i.sstatic.net/eHMw9.jpg I have tried changing the chart fill when creating the chart, but it didn't work at a ...

Combine rows with the same value in the first column of an HTML table

My HTML table has dynamic content, and I need to merge rows in the first column only if their values are identical. You can see an image of the table here. Specifically, if the values in the first column match, those rows should be merged together while le ...

I encounter difficulties using my static resources in the root route of my Express.js application

Can you guide me on how to implement styles and images from the assets folder in my webpage, specifically for the root route? As an example, I have a styles.css file located at assets/styles.css. In my code, I am using app.use(express.static('assets&a ...

Incorporating traditional Javascript classes for modeling in React development

Can traditional JavaScript classes be utilized in models within the MVC framework while using React, as opposed to relying on Redux or contexts & reducers which may impact reusability? If this approach is feasible, how can we efficiently 'subscribe&ap ...