vue-router: $router.push({query: this.myarray}) not updating the URL

Vue.js / vue-router versions

2.1.2

Reproduction Link

http://jsfiddle.net/ub9e33fm/2/

Steps to reproduce

  1. Click first link
  2. Click second link: see the difference in printed vars

What is Expected?

Clicking the second link will also update this.$route.query

What is actually happening?

this.$route.query is not updated

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 27 (5 by maintainers)

Commits related to this issue

Most upvoted comments

After more debugging, it looks like the issue was that on created() i was assigning a variable, filters to this.$route.query.

As soon as i removed that, setting the query string as my filters object updates works as expected.

The fix was to change my assignment in the created() method to:

this.filters = JSON.parse(JSON.stringify(this.$route.query));

from

this.filters = this.$route.query

Once I did that, I was able to use this.$router.replace({ path: this.$route.params[0], query: filters }); without any issues!

Hopefully this helps someone stuck with this!

Because a route is immutable (https://router.vuejs.org/en/api/route-object.html) Object.assign() is not able to modify it. FIx: don’t try to modify the route object:

query: Object.assign({}, this.$route.query, opt)

(from: https://stackoverflow.com/a/43441772/2112538 )

For anyone still having a similar problem and who cannot find the cause: perhaps you are reusing the reference to the same array in multiple route objects. Object.assign doesn’t do a deep copy. Mutating an array doesn’t trigger a route transition and in the subsequent route navigation triggered by router.push / router.replace the check in transitionTo recognizes no change since it compares the array to itself.

The solution is to work with an array like described here: Pure javascript immutable array

But doing a deep copy is a very weird but also reliable way to not have to write your code overly complicated:

JSON.parse(JSON.stringify(this.$route.query)));

Seems like a reactivity issue for $route.query. A quick workaround is to pass a copied array each time using arr.slice() http://jsfiddle.net/gtrasncw/

I just can’t router.replace({ query: {} })! Replacing to existing name or path works, query doesn’t. What am I doing wrong, guys? I want to remove query string.

thanks @kozie and @francoisromain , this ended up working for me as well

  methods: {
    query (params) {
      let query = Object.assign({}, this.$route.query, params)
      this.$router.push({ query: query })
      this.get(query)
    }
  }

I’ve just fallen back to using plain Javascript to update the URL after this.$router.push({ query: updatedQuery }), as cloning the object/array doesn’t seem to work for me on v3.0.1.

For all those searching in vain, here’s the workaround: window.history.pushState({}, '', 'index.html#/viewName?queryParam=' + this.$route.query.queryParam;

It’s not the most glamorous of solutions but it works. I can, moving forward, share the URL and with some changes, return to the view I specified.

If anyone is still having this issue, I am using following code as a solution:

if (Object.entries(this.$route.query).length !== 0 
    && this.$route.query.constructor === Object) {
  this.$router.replace({ query: {} });
 }

Ok so this works. Looks like pushing variables to the $router instead of the existing path and query does the trick. Finally, stumbled across something by accident while refactoring 😃

let updatedQuery = { ‘query1’: this.$route.query.query1, ‘eventType’: this.$route.query.query2 } let updatedPath = this.$route.path; this.$router.push({ path: updatedPath, query: updatedQuery });

Just as @fnlctrl said, pass a copied array instead of the direct reference.