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

<router-link> appears to cache dynamically generated path, after link has been followed for the first time #1255

Closed
TynesideGroup opened this issue Mar 15, 2017 · 16 comments

Comments

@TynesideGroup
Copy link

Vue.js / vue-router versions

2.2.4 / 2.3.0

Summary

This is difficult to explain, but hopefully the steps below will help you see the issue. The path property of a generated <router-link> appears to be work fine the first time it is called. After visiting the generated link and returning to the page which generates the link, the path appears to be cached to the original generated link that you clicked on and does not accurately reflect the params being passed to it.

Reproduction Link

http://217.182.65.138:8080
Note: App is running in yarn run dev mode, so you can see the application source files through your browser dev tools. This may assist you with debugging the issue if necessary.

Steps to reproduce

  • Visit Leaderboards page
  • Wait for table data to load
  • Once loaded, hover over each user to see that routes are correctly generated (/:username/:platform/overview)
  • Click one of the users to follow the link
  • Return to the Leaderboards page (you don't need to wait for the data on the new page to load)

What is Expected?

Once the table data on the Leaderboards page reloads, the links should still generate correctly.

What is actually happening?

Once the table data on the Leaderboards page reloads, all of the links point to the user you originally clicked on during the reproduction steps. The Chrome Vue dev tools plugin also shows the links with the correct params but the path appears to have been cached somehow to the user you originally clicked on.

Notes

I am not doing anything special for the links. The route is configured like this:

// Individual Player Stats
{
  path: '/:username/:platform',
  name: 'stats',
  component: Stats,
  redirect: {
    name: 'stats.overview'
  },
  meta: {
    breadcrumb: 'Stats'
  },
  children: [
    { path: 'overview', name: 'stats.overview', component: OverviewStats, meta: { breadcrumb: 'Overview' } },
    { path: 'operators', name: 'stats.operators', component: OperatorStats, meta: { breadcrumb: 'Operators' } },
    { path: 'rolling-data', name: 'stats.rolling-data', component: RollingDataStats, meta: { breadcrumb: 'Rolling Data' } }
  ]
}

I generate the links to that page from the Leaderboards page through a v-for loop (where the data being looped through comes from an API call) like this:

<tr v-for="(player, i) in leaderboard" :key="player.ubisoft_id">
  <td>{{ activeRecordsStart + i }}</td>
  <td>
    <router-link :to="{
      name: 'stats.overview',
      params: {
        username: player.username,
        platform: player.platform
      }
    }">
      {{ player.username }}
    </router-link>
  </td>
  <!-- etc -->
</tr>

I believe this is a bug but it may be an issue with our setup. Any assistance with identifying the cause would be highly appreciated, even if it is not necessarily confirmed as a bug in the end.

@TynesideGroup
Copy link
Author

TynesideGroup commented Mar 15, 2017

It might be worth adding that if I change the <router-link> to the following it works fine, but it feels sort of hacky to do it this way:

<router-link :to="{ path: '/' + player.username + '/' + player.platform }">
  {{ player.username }}
</router-link>

@posva
Copy link
Member

posva commented Mar 16, 2017

You'll have to provide a minimal repro. I tried and it's working fine: http://jsfiddle.net/m2tq3cLm/

@TynesideGroup
Copy link
Author

Not sure if the reproduction link I provided in my original comment was available at the time you attempted to create a minimal repro (it is back online now), but the example you have posted is not configured to accurately reproduce the issue we are having.

I have tried numerous ways to reproduce this issue in jsfiddle with a simplified version of our setup but, as is always the case when you're trying to prove a bug, it seems to works fine. Without replicating the complexity of our application in jsfiddle it will be difficult to show the bug occurring.

If I did replicate the complexity of our application (even though it isn't outside of the norm of vue, vue-router, vuex and axios) and replicate the bug in jsfiddle it would likely be even more difficult to diagnose than just viewing the reproduction link I have provided.

If possible, I would ask that you take a look at the reproduction link I provided and following the reproduction steps to see the issue. It is running in yarn run dev mode so you are able to see all of the .vue files etc. in the dev tools.

@posva
Copy link
Member

posva commented Mar 17, 2017

I have tried numerous ways to reproduce this issue in jsfiddle with a simplified version of our setup but, as is always the case when you're trying to prove a bug, it seems to works fine

In that case, it's probably related to your application code.

I checked, and it's quite strange, indeed but I really need a minimal reproduction to test it. Just so you know, using a :key="player.username" attribute in the router-link should fix your issue.
Maybe try with the repro I gave you and using v-for loops.

Two side notes: Nice site, I just started playing r6 yesterday 😆 , I have friends who have been playing for a while. In the leaderboards, your filters menu are always clickable, even when not visible, you should probably add the v-show on the ul element instead. Also consider using something like https://github.com/simplesmiler/vue-clickaway to close them when clicking outside

@TynesideGroup
Copy link
Author

I'll keep trying to get a reproducible example in jsfiddle, I think it'll end up at the point where almost all of our application code is there though! I will update this issue once I've got it broken in jsfiddle 😆

I tried your suggestion of :key="player.username" on the <router-link> but unfortunately the issue persists.

Thank you for your additional comments - it's a joint effort and most definitely a work in progress so minor issues like that will be fixed as we progress. I hope you're enjoying R6 as much as we do!

@posva
Copy link
Member

posva commented Mar 25, 2017

Closing due to inactivity. Please open a new issue with a reference to this one if you can follow up with more information.

@posva posva closed this as completed Mar 25, 2017
@Naeemo
Copy link

Naeemo commented Apr 11, 2017

@liam-potter Excuse me, did you get a repro or solve it somehow?

the path appears to be cached to the original generated link that you clicked on and does not accurately reflect the params being passed to it.

I am in this situation right now. Tried to get a repro last night but no luck, so I take a step back for now:
instead of
:to="{name: 'item', params: {id: item.id}}"
use
:to="{'/item/' + item.id}"

@TynesideGroup
Copy link
Author

@Naeemo Unfortunately I wasn't able to reproduce the issue in jsfiddle, however the issue does indeed still persist.

Perhaps you could offer a more detailed description of your setup? If it is similar to our setup then perhaps I can try to reproduce again.

@men232
Copy link

men232 commented Nov 30, 2017

I confirm, these conditions are necessary to reproduce:

  • Named routes
  • Route with children.
    Main route > child_1 > child_1/:id

router-link must used as a tag. if use button tag the problem is gone. As i understand.

State of route-link:
https://imgur.com/fEldd4m

Drawn element:
https://imgur.com/dxdqj7O

@thinksk
Copy link

thinksk commented Feb 15, 2018

This issue hasn't been solved yet. We are facing the same issue with our product as well. Is there any other better workaround to overcome this instead using a button?

@ma53
Copy link

ma53 commented Mar 15, 2018

@posva I'm also experiencing this issue. I tried for a couple of hours to reproduce it on both jsfiddle.net and codesandbox.io, but I haven't had any success. I understand there is little that can be done without a good reproduction, but can we at least have the issue reopened? In the meantime, I'll look into stripping down the project I'm working on to only what is required to reproduce the error so that I can host it somewhere public for your review.

@posva
Copy link
Member

posva commented Mar 15, 2018

Open a new issue once you have the minimal repro working please 🙂

@rlfrahm
Copy link

rlfrahm commented Aug 25, 2018

I just encountered this issue after I changed my app's main template to use <keep-alive></keep-alive>.

Changing this:

<transition>
    <keep-alive>
        <router-view></router-view>
    </keep-alive>
</transition>

To this:

<transition>
    <router-view></router-view>
</transition>

Solved the problem. This is what I get for copy-pasting!

@AverageHelper
Copy link

Same issue here, but...

@rlfrahm Your comment led me to this Vue forum post, which led me to the keep-alive docs.

Props:
include - string or RegExp or Array. Only components with matching names will be cached.
exclude - string or RegExp or Array. Any component with a matching name will not be cached.
...

While I'm fine with route caching for most things (like scroll position on my list views, which otherwise update dynamically anyway), my password change form needed to go in my keep-alive component's exclude prop. Thank you for leading me in the right direction!

@limeandcoconut
Copy link

This is still a problem. @men232 's comment was correct, re the circumstances required to reproduce.

@Serzhanov
Copy link

Serzhanov commented Sep 11, 2023

I've got a tricky solution if someone really needs to solve this problem.

router.beforeEach((to,from,next)=>{ if(to.fullPath==='/' && to.matched.length>=1){ next(to.matched[to.matched.length-1].path) } else{next()} })

So essentially, whenever there is no longer a route, it redirects the current cached URL to the last route match.

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

10 participants