Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

fix(nuxt): keep state in initial state instead of extracting it #7567

Merged
merged 4 commits into from
Sep 16, 2022

Conversation

pi0
Copy link
Member

@pi0 pi0 commented Sep 15, 2022

πŸ”— Linked issue

Resolves nuxt/nuxt#14927

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

#6455 adds payload.state (set by useState) to the extracted payload. This will cause hydration and unwanted behavior on navigation by orriding already initialized state.

This PR, makes behavior closer to Nuxt 2 by keeping state to the initial state inlined in the pages. Only payload data is now extracted.

Alternatives: We could instead keep extracting state and only try to set keys that are not assigned yet but it seems wrong performance wise if state is initial state it should be set once and if is same across pages, loading it adds to network overhead. We can revise it later with some better approach to only record state change diffs and include that in _payload.js somehow.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@pi0 pi0 added the ❗ p4-important Priority 4: bugs that violate documented behavior, or significantly impact perf label Sep 15, 2022
@netlify
Copy link

netlify bot commented Sep 15, 2022

βœ… Deploy Preview for nuxt3-docs canceled.

Name Link
πŸ”¨ Latest commit 6b87f56
πŸ” Latest deploy log https://app.netlify.com/sites/nuxt3-docs/deploys/63244d4bb076630007e7b39a

@pi0 pi0 marked this pull request as draft September 15, 2022 16:40
@danielroe
Copy link
Member

danielroe commented Sep 15, 2022

I would suggest not treating data differently from state. useState is pretty much identical to useAsyncData as far as data initialisation. Unlike Nuxt 2, where the store was a global object that was initialised no matter what page you started on, in Nuxt 3, state may only be initialised on a subset of pages.

It's also equally likely that users who have deliberately duplicated an asyncData key, such as (for example) an auto key defined in [slug].vue, will have issues with the current behaviour.

I agree we shouldn't override keys that are already defined.

@pi0
Copy link
Member Author

pi0 commented Sep 15, 2022

useState has two use cases. Main is to hydrate (sync) state from server to the client and one new use case of content module for custom data fetching. I agree second is valid but combining it with useState, means we should sacrifice one usage performance to each other (loading full state to the payload is duplicate if is same between two pages. something like navigation state is always the same and also in random example, we already bundled same js logic to reproduce initial (sync) state).

We might instead introduce new useData (nuxt/nuxt#14924) that is purposed for this. It can reuse same data namespace of useAsyncData.

@danielroe
Copy link
Member

danielroe commented Sep 15, 2022

I've raised a separate PR partially dealing with the issue of conflicting state/data keys: #7574.

If we really need to exclude data from payload, then what about, instead, only excluding data that has been set outside of a vue component instance? E.g. in a plugin. We could define on ssrContext which keys are 'initial' and which represent the payload?

(I'm still not convinced that removing state from the payload is the right solution, as the useState approach defaults to the concept of local state rather than global.)

@pi0
Copy link
Member Author

pi0 commented Sep 16, 2022

I thought about making differentiated behavior too but honestly, it makes composable behavior even more unpredictable if it behaves different when used in plugin or component contexts.

Actually, I made useState as a global state replacement initially. It was (and is its main purpose) useAsyncData for data fetching per page.

New useData can be exactly purposed for what we want to behave per-page rather than global/initial.

@pi0 pi0 marked this pull request as ready for review September 16, 2022 08:14
@danielroe
Copy link
Member

danielroe commented Sep 16, 2022

I would really appreciate it if you would wait an hour or two for me to write down my comments on this and #7569.

@danielroe
Copy link
Member

tldr; I think it's safe to disable the inclusion of useState data in the payload because we only just released full static mode - no objections to merging this PR as-is. (I think we may need to reconsider this approach in future, but that would be in the nature of an enhancement rather than a breaking change...)


I think there are several use-cases for it at the moment.

  1. It is a replacement for any kind of ref meant to be SSR-safe. This is typically write-once, and it may be updated in each successive page - in other words, it might be unique to each page. This would make sense to extract into a payload.
  2. It is a replacement for global state (e.g. nav menu display or not). This should not be extracted (more specifically, it shouldn't be updated on navigation).
  3. It is a replacement for an initial state. E.g. a list of navigation items or settings from a CMS. This only needs to be loaded once and shouldn't be extracted into a payload owing to the increased network payload.

With this change, useState becomes usable for nuxt/nuxt#11665 & nuxt/nuxt#11682. And I think that useData/usePageData would be a sufficient replacement for nuxt/nuxt#11418, with my suggested change. (This would be somewhat breaking as users would not have a way of extracting data into a payload which is in the global scope, e.g. shared across pages. But I think that is a necessary evil to prevent the Suspense issue I referred to - which would have been a problem anyway, independent of payload extraction.)

@pi0
Copy link
Member Author

pi0 commented Sep 16, 2022

Thanks for the nice summary and input @danielroe ❀️ Indeed this revert a short-lived behavior change we introduced in RC.10 for payload extraction making useState primarily usable for global/initial state such as navigation. And that we might include state changes as a future and non-breaking change enhancement to the payload extraction in the future.

@pi0 pi0 mentioned this pull request Sep 16, 2022
7 tasks
@pi0 pi0 merged commit 1ebdef7 into main Sep 16, 2022
@pi0 pi0 deleted the fix/payload-state branch September 16, 2022 10:49
@pi0 pi0 mentioned this pull request Sep 20, 2022
@danielroe danielroe added the 3.x label Jan 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
3.x ❗ p4-important Priority 4: bugs that violate documented behavior, or significantly impact perf
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[rc.10] static payload replaces current state
2 participants