Vue-router: Asynchronous data hook

Created on 23 May 2015  路  17Comments  路  Source: vuejs/vue-router

I'm finding myself doing a deep watch of router.params in all of my components used by <router-view> in order to reload the data loaded/initialized in my components' created handler. Is there a better way about this? Should this automatically happen for navigation changes in the same router component?

Most helpful comment

Yeah, thanks! I did actually figure that out in the end. Here's some sample code for future people.

export default {
    props: ['lessonNumber'],
    data() {
      return {
        lesson: {
          title: "",
          video: "",
          description: ""
        }
      }
    },
    ready() {
      this.fetchNewLesson()
    },
    methods: {
      fetchNewLesson() {
        this.$http.get('http://localhost:4000/api/v1/lessons/' + this.lessonNumber).then(function (response) {
          this.$set('lesson', response.data.data)
        })
      }
    },
    watch: {
      lessonNumber: {
        handler: function() { this.fetchNewLesson() },
        deep: true
      }
    }
  }

All 17 comments

There is going to be a data option to route definitions, which allows you to load some data based the the route before actually initializing/updating your components.

Btw, thanks for these issues! It's really helpful to have feedback based on actual usage even before it's released :)

:+1:

How do you plan to handle async data? In my case, I'm loading from an external data source.

If I navigate to a page within the same component, causing a new set of data to be loaded, what happens between the navigation and data loading? Does the page remain unchanged until the data is loaded? Will there be an option to clear the data? I'd like to keep the UI feeling snappy, and if there's a delay between page updates after navigating without a way to clear the data, it'll feel really sluggish.

What do you mean by "clear the data"?

Currently a VM's data is not cleared or reloaded on navigation changes within the same component (e.g. navigating from /entries/1 to /entries/2 where entries is the shared component). In order to load new data, I'm watching for changes in the route params, then fetching new data based on the new route params. Before that data is fetched, I'm clearing the data set on the last fetch so I can conditionally display a "loading" indicator (so that navigation has a clear effect on the page).

There's an option called alwaysRefresh (maybe could use a better name) which basically means if the params change this component should just be reloaded.

Although I haven't really put enough thought to the async data handling part yet - maybe there could be a more elegant solution.

Alternatively - we can expose a loading flag on the route object to indicate that the async data function is still awaiting its result.

alwaysRefresh and loading are not implemented, so should I just watch the $route.params for now?

By the way how exactly should I watch vm.$route.params ?
I tried passing it to vm.$data.params

data: {
    params: vm.$route.params
}

and

vm.$watch('params', callback, {deep: true})

does not work.

The problem is that vm.$route.params was never updated when url changes from /entries/1/ to /entries/2/...

@yyx990803

@yyx990803
Same here. I'm trying to 'force' reload my page components when switching from route
whatever/1 to whatever/2.

How would you go about to watch the $route.params anyway ?

Thanks

+1 Also interested in refreshing component data based on a change in param.

Did you find a solution to this @rleger? I'm still trying to reload a component's data upon a param change.

@benwalks the best I could come up with is to watch the route params.. not elegant but for lack of a better solution it works.

ready() {
  this.$watch('$route.params', this.handleChange , { deep: true })
}

Well guys.. there has been a solution using route.data, read about it here, just as Evan wrote when he closed the issue on 11 Jun 2015. Maybe he was too busy to explain it here..

The reason the component isn't reloaded when route change from whatever/1 to whatever/2 is that their route.canReuse is set to true by default, so they are reused and the lifecycle hooks were never fired again. A straightforward way would be to set canReuse to false, but using route.data would be the best solution.

On 1 Oct 2015 I hadn't read though the docs carefully, so I posted the problems (which weren't) here. Later I read the docs and solved the problems, and totally forgot about this issue.... So I hope this helps @benwalks @rleger

Yeah, thanks! I did actually figure that out in the end. Here's some sample code for future people.

export default {
    props: ['lessonNumber'],
    data() {
      return {
        lesson: {
          title: "",
          video: "",
          description: ""
        }
      }
    },
    ready() {
      this.fetchNewLesson()
    },
    methods: {
      fetchNewLesson() {
        this.$http.get('http://localhost:4000/api/v1/lessons/' + this.lessonNumber).then(function (response) {
          this.$set('lesson', response.data.data)
        })
      }
    },
    watch: {
      lessonNumber: {
        handler: function() { this.fetchNewLesson() },
        deep: true
      }
    }
  }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gil0mendes picture gil0mendes  路  3Comments

druppy picture druppy  路  3Comments

thomas-alrek picture thomas-alrek  路  3Comments

mitar picture mitar  路  3Comments

lbineau picture lbineau  路  3Comments