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

Clear way to re-use the component of the matched page when language switching causes a navigation to a different locale prefix #2853

Open
2 of 4 tasks
danwithabox opened this issue Mar 18, 2024 · 8 comments

Comments

@danwithabox
Copy link

danwithabox commented Mar 18, 2024

Describe the feature

I wish to keep page state when a language switcher causes the URL to change.

Currently, out-of-the-box, the URL change causes a component re-render.
I would have guessed Vue router's goal of re-using and updating components when possible would apply, since the pages are the same, only the locale have changed.
Instead, a console log on onMounted shows that a fresh component is mounted.

Is this intended behaviour?
It seems counter-intuitive to me, but I have not found documentation nor issues about.

I tried a quick workaround (in pages/index.ts):

<script setup lang="ts">
definePageMeta({
    key: (route) => route.name.split("___")[0],
});
</script>

This works, since the postfixed pathnames seem to use a ___ separator, e.g.:

index___en-US
index___en-US___default
index___en-GB

With some more digging around, I changed the code to make it less hacky by avoiding the magic string ___:

<script setup lang="ts">
definePageMeta({
    key: (route) => {
        const key: string = useRouteBaseName()(route) ?? route.fullPath;
        return key;
    },
});
</script>

I am definitely not sure that this is the best way to achieve what I want.
Could we have a dedicated option for this, or at least an official snippet in the documentation?

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

@danwithabox
Copy link
Author

I tried to double-check the documentation for any snippets or info I might've missed on this, but at the time of writing the documentation is broken.

@BobbieGoede
Copy link
Collaborator

I tried to double-check the documentation for any snippets or info I might've missed on this, but at the time of writing the documentation is broken.

Sorry about that, the documentation was broken yesterday but it should be working again!

Is this intended behaviour?
It seems counter-intuitive to me, but I have not found documentation nor issues about.

This is intended behaviour, when switching between languages you're essentially navigating to a different page with the same behaviour as you normally would experience. I think using a no_prefix routing strategy would work around this, but that would come with its own SEO implications.

Could you create a reproduction to show an example of page state that is lost/re-rendered?

@danwithabox
Copy link
Author

danwithabox commented Apr 4, 2024

Minimal example:
https://github.com/danwithabox/issue_nuxt-modules-i18n_2853

After clone, npm start, out-of-the-box it will run without the definePageMeta workaround.

Should see 3 things:

  • ways to choose locale: first two ways change the URL, third way doesn't
  • a Nuxt UI <UCommandPalette> with localized text and component-local state
  • an image, representing requests that should run only when pages are considered visited (and pretend that a locale change is decided to not count as such)

Without the workaround:

  • the command palette component resets, demonstrating unexpected and undesired state loss
    • a state store would fix this, but effectively banning component-local state because of i18n is overbearing imo
  • the image reloads
    • normally this wouldn't be visible due to browser caching, but here I bypassed it with the changing query param, this is more visual than checking the network panel for requests
    • this also relates to one person's annoyance that I saw in the Nuxt discord: i18n SetLocale() problem
  • the third way to change locale ("assignment to locale") doesn't cause these issues, but the URL isn't updated either

To enable the workaround, uncomment key: i18n_pageKey, at /pages/index.vue:L10
⚠️ and reload the page, as HMR doesn't effect this ⚠️ because of how definePageMeta is processed, which is also the reason why it can't be programmatically changed, but that's possibly not needed anyway.

With the workaround enabled:

  • changing locale now won't cause a component mount, just a component update, see logs in console
  • effectively acts as the "assignment to locale" way of choosing locale, while also updating the URL

This behavior is what I would prefer in most cases, because

  • it does not re-create a whole component tree when a more performant update would suffice (though, ofc, people don't hammer language switchers to make this the greatest concern)
  • it just feels better! both as a user, and as a dev thinking about state management

I do like the granularity of specifying on which pages I want to have either behavior, via the key prop in definePageMeta.
I do agree that the current default can be intended behaviour, but not the only intended behaviour.
I'm fine with specifying it for every page, but some people may want a global config, not sure.

I'd love an importable utility like i18n_pageKey() in my example, or even just an official code snippet in the documentation.
Any other solution is welcome too, as long as it's a canonical solution that I don't have to worry about being broken by an update.

@BobbieGoede
Copy link
Collaborator

@danwithabox
I think your reproduction repo is private, I can't access it 😅

@danwithabox
Copy link
Author

Indeed, I knew I forgot something! Should be good now, cheers 🫠

@kazupon
Copy link
Collaborator

kazupon commented Apr 12, 2024

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

Thanks!

@kazupon kazupon closed this as completed Apr 12, 2024
@danwithabox
Copy link
Author

I will risk it and ping @BobbieGoede, I don't think this issue should be closed before input from you, maybe I should've pinged when I made my repo public 🤷‍♂️

I don't think opening a new issue just to bump this would be appreciated. And I can't really "follow up with more information" until some reaction to my repro / example 😅

@BobbieGoede
Copy link
Collaborator

Ah I did somehow forget to check this out again, the ping was necessary 😅..

I still have to give it a thorough look, I understand the benefits of not mounting the page again but we should consider what could be possible drawbacks as well.

There's been a few PRs with feature proposals that also touch on some core features that could have some overlap with each other including this, I'll reopen this and assign myself so we can keep the discussion open and I will look into it when I have more time 😥.

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

3 participants