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

Nested Dynamic Route change causes parent route to re-render #1408

Closed
carrickjason opened this issue Aug 18, 2017 · 9 comments
Closed

Nested Dynamic Route change causes parent route to re-render #1408

carrickjason opened this issue Aug 18, 2017 · 9 comments

Comments

@carrickjason
Copy link

carrickjason commented Aug 18, 2017

First off, huge thanks for Nuxt. I love it!

I have a project with a simple folder structure similar to the following:

pages/
--items.vue
--items/
----_id.vue

I have included a <nuxt-child/> inside items.vue along with a list of items that link to different id's. _id.vue simply renders a modal that displays info based on the id passed as a param.

This is all working and rendering properly except that each time an item is clicked, the items.vue component re-renders causing it reset its state and lose the users scroll position.

Is this expected behavior? Is it possible to have dynamic nested routes without re-rendering their parent with each route change?

This bug report is available on Nuxt.js community (#c1253)
@ydnar
Copy link

ydnar commented Aug 31, 2017

Curiously, with 1.0.0-rc8 I observe the opposite behavior. I have a project with nested views:

pages/
--index.vue
--index/
----_id.vue

The outer/root view (index.vue) displays search results, keying off a query string parameter (?q=<terms>). <nuxt-link> links that change the query string parameter, e.g.:

/?q=foo
/?q=bar

…do not cause the outer view to re-render. The asyncData, fetch, and mounted hooks do not fire after the initial render.

Is this as-designed? Is there a way to specify that query string parameters affect a route and should cause a re-render?

@dotneet
Copy link

dotneet commented Oct 6, 2017

I think this issue is related to #1761 .
fixPrepatch() resets a parent view's state.

https://github.com/nuxt/nuxt.js/blob/dev/lib/app/client.js#L359

I'm not sure why fixPrepatch() is needed.

I've removed following line and confirmed this change provide expected behavior for me.
https://github.com/nuxt/nuxt.js/blob/9e4f864e4d25af2e9668767bb297182656e19cba/lib/app/client.js#L557

@dotneet
Copy link

dotneet commented Oct 6, 2017

@Atinux Thank your for creating great useful framework. If you have a time, could you tell me what situation needs fixPrepatch().

@wuyongzhi
Copy link

i have the same problem, how to solve it?

@Atinux
Copy link
Member

Atinux commented Oct 13, 2017

Actually, fixPrepatch is there to merge the result of asyncData when we are on a dynamic route without having to watch $route, I will investigate on it, but It will help me a lot to have a small reproduction repo please.

@dotneet
Copy link

dotneet commented Oct 13, 2017

Hi @Atinux,
small reproduction repo is here:
https://github.com/dotneet/nuxt-issue-1408

@dotneet
Copy link

dotneet commented Oct 19, 2017

Hi @Atinux,

Do you think this patch is worth to PR?
using getChangedComponentsInstances() instead of getMatchedComponentsInstances() in client.js, We can get around this problem I think.

getMatchedComponentsInstances() returns all components that is matched to new path.
This is root cause of this problem. To solve the problem, nuxt should apply a fixPrepatch() to components that will be changed by moving path.

export function getRouteRecordWithParamNames (route) {
  return route.matched.map(m => {
    let paramNames = m.path.match(new RegExp(':[^\\/]+$', 'g'))
    let paramName = null
    if (paramNames !== null && paramNames.length > 0) {
      paramName = paramNames[paramNames.length - 1].substring(1)
    }
    return {
      routeRecord: m,
      paramName: paramName
    }
  })
}

export function getChangedComponentsInstances (to, from) {
  let t = getRouteRecordWithParamNames(to)
  let r = []
  let parentChange = false
  for (var i = 0; i < t.length; i++ ) {
    var paramName = t[i].paramName
    var instances = t[i].routeRecord.instances
    instances = Object.keys(instances).map(function (key) {
      return instances[key]
    })
    if (parentChange) {
      r = [].concat(r, instances)
    } else if (paramName !== null) {
      if (to.params[paramName] !== from.params[paramName]) {
        parentChange = true
        r = [].concat(r, instances)
      }
    }
  }
  return r
}

dotneet added a commit to dotneet/nuxt.js that referenced this issue Oct 29, 2017
Atinux added a commit that referenced this issue Oct 31, 2017
fix unexpected state resetting #1408
@Atinux
Copy link
Member

Atinux commented Oct 31, 2017

PR merged

@lock
Copy link

lock bot commented Nov 3, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 3, 2018
@danielroe danielroe added the 2.x label Jan 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants