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

fix(vue-app): this.$nuxt.refresh doesn't refresh every fetch hooks #9530

Open
wants to merge 12 commits into
base: 2.x
Choose a base branch
from

Conversation

ms-fadaei
Copy link
Contributor

With this fix, layout fetch, layout child components fetch (including the page), and page child component fetch will be called during the Nuxt refresh helper.

Types of changes

  • Bug fix (a non-breaking change which fixes an issue)
  • New feature (a non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Description

In the current version of the Nuxt when we call $nuxt.refresh(), the page fetch will be called if the current page has a fetch, otherwise, the child components fetch method will be called.

with this fix:

  • if the layout is enabled:
    • if the layout itself has the fetch, it will be pushed to the call list
    • if the layout child components (including the page) have the fetch, they will be pushed to the call list
  • if the layout is disabled:
    • if the page itself has the fetch, it will be pushed to the call list
    • if the page child components have the fetch, they will be pushed to the call list

Caution: What about nested routes? layout fetch will be inserted twice? can use set instead of array to prevent duplication?
fix: #9439

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly. (PR: #)
  • I have added tests to cover my changes (if not applicable, please state why)
  • All new and existing tests are passing.

@codecov-commenter
Copy link

codecov-commenter commented Jul 7, 2021

Codecov Report

Merging #9530 (0a117cb) into dev (123206c) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##              dev    #9530   +/-   ##
=======================================
  Coverage   65.19%   65.19%           
=======================================
  Files          94       94           
  Lines        4155     4155           
  Branches     1172     1172           
=======================================
  Hits         2709     2709           
  Misses       1167     1167           
  Partials      279      279           
Flag Coverage Δ
unittests 65.19% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 123206c...0a117cb. Read the comment docs.

} else {
// Get all component instance to call $fetch
// get layout component
const layout = this.$children.find((component) => component._name?.toLowerCase().includes("layouts"))
Copy link
Member

@pi0 pi0 Jul 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor suggest: Maybe we can use let root = page and change it to parent layout instance if exists? (this way we merge to branches)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this also makes sense to only crawl everything once, also keeping getChildrenComponentInstancesUsingFetch simple. What was your opinion on that @ms-fadaei?

@pi0
Copy link
Member

pi0 commented Jul 7, 2021

What about nested routes? layout fetch will be inserted twice? can use set instead of array to prevent duplication?

Can you please ensure about this? If is a case, we might make use of WeakSet to dedup. (Note: IE support 🤷)

Also can you please check behavior when page does not having $fetch but layout does?

@ms-fadaei
Copy link
Contributor Author

Can you please ensure about this? If is a case, we might make use of WeakSet to dedup. (Note: IE support 🤷)

Also can you please check behavior when page does not having $fetch but layout does?

I checked that right now. it not working properly with nested routes (then I should refactor the code)
I checked that too and it seems everything is right!

@ms-fadaei
Copy link
Contributor Author

@pi0
what you thinking about getChildrenComponentInstancesUsingFetch
https://github.com/nuxt/nuxt.js/blob/HEAD/packages/vue-app/template/utils.js#L56-L68

If a child has the fetch, children of it will not be considered!

@ms-fadaei
Copy link
Contributor Author

And I realized the sequence call of fetch (first parent then child) is not guaranteed! (in the current version this is just about nested routes because of limited fetch calls but in my version, this occur in every parent-child relations)

@ms-fadaei
Copy link
Contributor Author

@pi0 @clarkdo I'm done with this PR.

We still have two edge cases that I mentioned above with refresh handler and they aren't new! they exist from the last versions

@lihbr
Copy link
Member

lihbr commented Jul 27, 2021

Hey friends, what's up on this one?
What remains to be changed/discussed to lead to a merge? or is it just awaiting a review?

Cheers!

@pi0 pi0 mentioned this pull request Aug 11, 2021
Copy link
Member

@danielroe danielroe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main thing we still need to handle is:

@lihbr
Copy link
Member

lihbr commented Nov 29, 2021

I'll try to have a look at the last bit @danielroe mentioned this week 💪 Keeping you up-to-date!

@lihbr
Copy link
Member

lihbr commented Dec 2, 2021

OK, I'm having a bit of trouble understanding the "duplicate fetch" maybe issue mentioned above.

Looking at the changes, 3 things have been achieved:

  1. getChildrenComponentInstancesUsingFetch() has been modified to handle an exclude array, stopping the crawling if a node from exclude is encountered during the crawling process;
  2. On the pages.map(), the callback now loop only over the children component of the current page, theoretically deduplicating redundant calls (? not 100% confident on that one, but that's what I understand);
  3. After the pages.map(), the refresh() method now looks for a layout, if one it adds its own fetch and crawls its children component, excluding pages and their offspring.

Taking all of those changes individually they seem pretty straightforward to me. Basically, the refresh() method now achieve that kind of resolution for fetch hooks (I had budget for an animation today):

refresh

I don't really see how we can end up with duplicate calls here, or at least how we can end up with duplicate calls we didn't have already before(?)

Now, maybe where I'm wrong is on my understanding of the getMatchedComponentsInstances() function. To me, that function gets each page component actually displayed on the current route, so from my gif above ~/pages/blog.vue & ~/pages/blog/index.vue? I'm not sure about that function behavior as it seems to access properties of Vue Router current route which I'm not aware of/are Nuxt specific(?): https://router.vuejs.org/api/#route-object-properties

If I'm wrong here and there's definitely something leading to duplicated behaviors, I'm not sure however a set would solve the issue? Or maybe it would? I'd be afraid only some of the deduplicated hooks get called and that the others remain stale (a.K.a. no new data?)

Let me know!

@pi0
Copy link
Member

pi0 commented Jun 23, 2022

@ms-fadaei @lihbr Can you please check the latest nuxt-edge? I believe #10489 should address the issues by refetching on all children. If not happy to reopen and improve 👍🏼

@pi0 pi0 closed this Jun 23, 2022
@lihbr
Copy link
Member

lihbr commented Jun 24, 2022

Hey there,

Unfortunately, this doesn't appear to fix the issue as the component-crawling function still starts from the page component instead of the layout.

Maybe I'm doing something wrong, here's my repro on edge: nuxt_nuxt.js_9530_1.zip

@pi0
Copy link
Member

pi0 commented Jun 24, 2022

Thanks for checking @lihbr. @ms-fadaei Would you please rebase your branch to dev?

@pi0 pi0 reopened this Jun 24, 2022
@ms-fadaei
Copy link
Contributor Author

ms-fadaei commented Jun 24, 2022

Thanks for checking @lihbr. @ms-fadaei Would you please rebase your branch to dev?

Hi Pooya,
Done!

@@ -214,6 +221,24 @@ export default {

return Promise.all(p)
})

<% if (features.fetch) { %>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danielroe danielroe added the 2.x label Jan 18, 2023
@danielroe danielroe added the bug label Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

this.$nuxt.refresh doesn't refresh every fetch hooks (^2.12.0)
6 participants