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

beforeRouteUpdate never calls next callback #1582

Open
bdoms opened this issue Jul 10, 2017 · 17 comments
Open

beforeRouteUpdate never calls next callback #1582

bdoms opened this issue Jul 10, 2017 · 17 comments

Comments

@bdoms
Copy link

bdoms commented Jul 10, 2017

Version

2.7.0

Reproduction link

http://jsfiddle.net/znmLks2w/2/

Steps to reproduce

Create a component with a beforeRouteUpdate guard that passes a callback to the next function.

What is expected?

The callback function should be called.

What is actually happening?

The callback is never called.


In my example I have both beforeRouteEnter and beforeRouteUpdate pointing to the exact same function. beforeRouteEnter works exactly like I expect, but beforeRouteUpdate does not. Click on the links to try to add one to the displayed value and you'll notice it works the first time but never any of the subsequent times.

If this behavior is purposeful then I would consider it a documentation bug - the docs need to be absolutely clear that next behaves differently depending on where you're calling it from. But even as I type this I'm realizing that if that's the case then it's terrible design. It should work the same way regardless.

@posva
Copy link
Member

posva commented Jul 11, 2017

The difference between both hooks is that enter doesn't have access to this so it needs the callback, while update has access to this. But I agree it should be more consistent, it's quite usual to have the same function in both hooks.

@thatguystone
Copy link

I'd say that this is a bug, not an improvement. Consider when using <router-view :key="...">, it becomes impossible to access the new component, so you can't inject data. See: http://jsfiddle.net/thatguystone/nypp9jma/1/

@amertum
Copy link

amertum commented Aug 2, 2017

I've just step on this problem. Could it be explained in the documentation on the navigation-guards page ?

@arnabrahman
Copy link

Just discovered this problem.

@justin-hackin
Copy link

Also observing this problem

@LinusBorg
Copy link
Member

LinusBorg commented Aug 25, 2017

I understand your confusion, but if you look at the documentation closesly, it states that passing a callback to next() is only necessary (and supported) in beforeRouteEnter, because we can't access this in that hook.

Both beforeRouteUpdate and beforeRouteLeave do have access to this, so the callback is unnecessary and therefore not supported.

Solution: just use this.yourdataProp = 'yourvalue' to change data.

I will see if I can come up with a quick PR for the docs to stress this difference as this has come up a couple of times already.

@bdoms
Copy link
Author

bdoms commented Aug 25, 2017

While updating the docs may help a few people who pay close attention understand what's happening better, it does not actually solve the problem, which is that developers expect a framework like Vue to provide a consistent interface. Just because the callback is unnecessary in some cases is not a good reason to make the same function behave differently depending on where it's called from. With two varying implementations that any reasonable person would expect to do the same thing, it means that the confusion is going to persist even if it's spelled out clearly in the docs. Plus, it also means that every developer who runs into this has to re-invent the wheel and figure out a way to detect and handle this situation.

Let me illustrate. Given this setup:

component1 = {
    beforeRouteEnter: myFunction
}
component2 = {
    beforeRouteUpdate: myFunction
}

What seems more intuitive, natural, and easy for developers? This:

myFunction = function(from, to, next) {
    // somehow detect which hook called this function
    if (calledByEnter) {
        next(myCallback)
    }
    else {
         next()
         myCallback(this)
    }
}

Or this:

myFunction = function(from, to, next) {
    next(myCallback)
}

The situation currently requires the former. I think the people commenting in this thread - and the project as a whole - would benefit from the latter.

@LinusBorg
Copy link
Member

LinusBorg commented Aug 25, 2017

You might have a point there, I'll reopen #1676 for further discussion, because that ticket was apprearantly requesting that change as well and is newer.

@posva
Copy link
Member

posva commented Aug 25, 2017

@LinusBorg what's the difference? I really see the same FR in both issues

@LinusBorg
Copy link
Member

LinusBorg commented Aug 25, 2017

No difference, really. I just feel that bdoms has made a good case that should at least be discussed. I'm not convinced yet if offering a callback for all in-component hooks is actually optimal either, but it's worth to think about so I wanted to have an issue open about it, I dont really care which.

We can also reopen this and I'll close the dupe again.

@posva
Copy link
Member

posva commented Aug 25, 2017

Ah, I see what happened 😆 This one is still opened. I personally think this is worth adding. It's convenient to pass the same function to both hooks. I'll close the other one

@LinusBorg
Copy link
Member

Oh... it's realy time for bed for me.

@lionel-bijaoui
Copy link

I don't understand how you are supposed to get this to work.
I have updated the fiddle to change x value on beforeRouteUpdate.
On update, you don't have access to this as far as I was able to do.
Please, could you explain how to make this work ?
My guess is some .bind(this) might be necessary or something. This is so frustrating, I tried a lot of things and nothing is working so far...

@jimmywarting
Copy link

What solution are you guys using now?
I had to dupe my code to do same thing in both beforeRouteEnter + beforeRouteUpdate

@posva posva added the has PR label Mar 26, 2019
@dariodepaolis
Copy link

What solution are you guys using now?
I had to dupe my code to do same thing in both beforeRouteEnter + beforeRouteUpdate

Actually I'm doing the same, duplicating code in Enter and Update, I could create a global function and call it changing the target (this or vm), or somebody found another more elegant solution?

@y-nk
Copy link

y-nk commented May 14, 2019

@dariodepaolis i'm not sure it's the "best pattern" but I faced this and solved it by a mixin :

export default f => ({
  beforeRouteEnter: f, beforeRouteUpdate: f
})

which i use in most cases like this :

import beforeRoute from '@/mixins/beforeRoute
import store from '@/store'

export default {
  mixins: [beforeRoute(
    (to, from, next) => store.dispatch('item/fetch', to.params.id)
      .then(() => next())
      .catch(() => next('/404'))
  )],

  computed: {
    ...mapState({
      item(state) { return state.articles[this.$route.params.id] }
    })
  }
}

(but i don't require access to this)


I do understand the major difference between beforeRouteEnter and beforeRouteUpdate, but i somehow wished for a beforeRoute instead, either in the router routes or component. (the one in the routes is only called when the route is reached from the browser i believe, so navigating to it wouldn't trigger the guard)

What's mainly counter-intuitive is that while beforeRouteEnter is defined in the component, it is not really a method of the component since it's called before the component is created...

@omushpapa
Copy link

omushpapa commented Oct 29, 2020

I'd say that this is a bug, not an improvement. Consider when using <router-view :key="...">, it becomes impossible to access the new component, so you can't inject data. See: http://jsfiddle.net/thatguystone/nypp9jma/1/

This is got me. You really don't have access to the next component.

I resolved to fetching data in beforeRouteUpdate saving to store and then using created to get the value from store.

Update
created is called asynchronously. To this point, beforeRouteUpdate and beforeRouteEnter have proved not useful due to the limitation on beforeRouteUpdate

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