Skip to content

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

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

Closed
kvdmolen opened this issue Feb 20, 2017 · 27 comments · Fixed by #1291
Closed

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

kvdmolen opened this issue Feb 20, 2017 · 27 comments · Fixed by #1291
Labels

Comments

@kvdmolen
Copy link

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

@znck
Copy link
Member

znck commented Feb 22, 2017

$route.query is updated on next click. Either click twice on second link or after clicking second link, click first link.

@anishdcruz
Copy link

@znck any possible hack for this issue?

@znck
Copy link
Member

znck commented Mar 30, 2017

/ping @posva Could you fix this? Or share a hack!

@fnlctrl
Copy link
Member

fnlctrl commented Mar 30, 2017

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/

yyx990803 pushed a commit that referenced this issue Apr 6, 2017
* make a copy when query param value is an array

* fix param type
@kvdmolen
Copy link
Author

kvdmolen commented Aug 8, 2017

Unfortunately, the problem remains when property {name} is added to route.push() method:

http://jsfiddle.net/ub9e33fm/12/

Version

2.7.0 (Edge)

Reproduce

  1. Click first link (?q=foo)
  2. Click second link (?=foo,bar)

See the $route.query not being updated with bar

  1. Click second link again. Now you see the updates.
  2. Remove name: 'home' from both this.$router.push lines
  3. Rerun. Now it works.

@adntin
Copy link

adntin commented Sep 22, 2017

if this.$router.push query of parameter is array , Could you fixed this? @kvdmolen

@javoski
Copy link
Member

javoski commented Sep 22, 2017

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

@timpalac
Copy link

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.

@mitchkramez
Copy link

@timpalac this is the exact same problem i'm currently dealing with - solved the exact same way. ++ on the solution as it actually works.

@timpalac
Copy link

Here's an alternate solution that works with back/forward buttons on the browser ... just add a second route with the same component and flip back and forth.

const routes = [ { path: '/results', component: searchResults }, { path: '/result', component: searchResults } ];

I'd really like to see a feature added to update the query string in the URL, it's absurd that I have to hop routes in order to get my query string updated without breaking the browser.

@mitchkramez
Copy link

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!

@timpalac
Copy link

Unfortunately that doesn't seem to update the URL to match. Who knows, maybe I'm doing it wrong.

@francoisromain
Copy link

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 )

@timpalac
Copy link

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 });

@acidjazz
Copy link

acidjazz commented Aug 9, 2018

Why is this closed @kvdmolen ? what's the solution? should this not update the URL?

@kozie
Copy link

kozie commented Oct 19, 2018

@francoisromain This is exactly what it is ^_^ made sense and it works like a charm! Thanks 👍

@acidjazz Well, as @francoisromain stated, it's an immutable object so it should be used differently than plain objects and such. Doesn't really seems like a bug, though ;)

@acidjazz
Copy link

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)
    }
  }

@pfeiferbit
Copy link

pfeiferbit commented Jan 24, 2019

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)));

@yuliai
Copy link

yuliai commented Mar 13, 2019

@pfeiferbit thanks a lot!
It works for me.

@emuter
Copy link

emuter commented May 17, 2019

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.

this.$router.push({name:'posts', query: { page: this.$route.query.page }}); this works for me.

@MeikelLP
Copy link

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!

This is still the correct answer for me. Seems like a bug.

@vintprox
Copy link

vintprox commented Aug 5, 2019

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.

@WhiteBookmark
Copy link

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: {} });
 }

@snovity
Copy link

snovity commented Oct 3, 2019

I'm having this issue with 3.8.4, not doing anything fancy, just updating with query param (no arrays, a completely new object). Keeping everything the same and navigating to a different route correctly applies query params, doing push for the same route with new query params does nothing.

cc @posva

@snovity
Copy link

snovity commented Oct 3, 2019

I ended up implementing a refresh route for now, going to it with new query redirects back with those new query params.

export default {
  name: "refresh",
  beforeRouteEnter(to, from, next) {
    next((instance) => {
      instance.$router.replace({
        name: from.name,
        params: from.params,
        query: to.query
      });
    })
  },
};

@snovity
Copy link

snovity commented Oct 4, 2019

Ok, scratch everything above, in my case it was a missing next() call in on the beforeRouteUpdate hook in the original route

beforeRouteUpdate(to, from, next) {
  this.rerender();
},

after I did this

beforeRouteUpdate(to, from, next) {
  this.rerender();
  next();
}

things started working.

Not sure if possible, but some warning in console about not called next (like after several seconds) would be helpful for a newbie as myself.

@posva
Copy link
Member

posva commented Oct 4, 2019

Locking as the issue is quite old and multiple conversations are getting mixed up

Not sure if possible, but some warning in console about not called next (like after several seconds) would be helpful for a newbie as myself.

It's not possible because a guard can be async and take a long time

@vuejs vuejs locked as resolved and limited conversation to collaborators Oct 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.