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

Proposal: Preserve ViewModel state on live-reloads #1151

Open
matthewp opened this issue Dec 14, 2018 · 8 comments
Open

Proposal: Preserve ViewModel state on live-reloads #1151

matthewp opened this issue Dec 14, 2018 · 8 comments

Comments

@matthewp
Copy link
Contributor

One problem folks have today is that when live-reload occurs it removes all state that's not in the URL. We could possibly improve upon this by saving ViewModels (serializing them perhaps) and restoring them later. Will take more thought to figure out but I wanted to get this proposal out there.

@frank-dspeed
Copy link
Contributor

maybe we should simply make a guide for serialize and hydrate viewModel to localstorage?

@matthewp
Copy link
Contributor Author

@frank-dspeed do you mean how to do it manually? That's not a terrible idea.

@chasenlehara
Copy link
Member

Two thoughts on this:

  1. Riffing off what Frank said, maybe this can be provided as another module that makes this really easy? Does it make more sense to opt in/out of this at the app level or component level?

  2. This feels conceptually related to how requests made during SSR are cached and made available to the client-side app. Is there something to be shared there?

@justinbmeyer
Copy link
Contributor

justinbmeyer commented Dec 18, 2018

My comments on time-travel debugging might be related: canjs/canjs#4529

@justinbmeyer
Copy link
Contributor

@chasenlehara it's related, but SSR data caching is far more simple as requests are more or less stateless. It's so simple that it's very unlikely the same approach can be used.

The hard part is how to deal with side effects. Say I wrote a component like:

ViewModel: {
  todos: "any",
  connectedCallback(){
    Todo.getList({}).then( (todos) => {
      this.todos = todos;
    })
  }
}

Do we serialize todos? How do we make sure they get converted to the Todo type? Do we run connectedCallback() again?

I think we should identify what sorts of state we really want to "keep" and which we do not. For example, a tab-like component:

tag: "my-tabs",
view: `
  {{# eq(state, "toys") }}
    CONTENT
  {{/ eq }}
  {{# eq(state, "tots") }}
    CONTENT
  {{/ eq }}
`,
ViewModel: {
  state: "string"
}

What it seems we would really need is just a way to save the last value to localStorage and use it as the default value:

tag: "my-tabs",
view: `
  {{# eq(state, "toys") }}
    CONTENT
  {{/ eq }}
  {{# eq(state, "tots") }}
    CONTENT
  {{/ eq }}
`,
ViewModel: {
  state: {
    type: "string",
    setLastValueAsDefaultInLocalStorage: true
  }
}

The problem here is what to do if there are multiple my-tabs

@matthewp
Copy link
Contributor Author

Just a sidebar, as it relates to live-reload localStorage is not needed as the browser doesn't actually refresh. We can just save the state in a Map of some kind in memory.

@frank-dspeed
Copy link
Contributor

frank-dspeed commented Dec 18, 2018

@justinbmeyer in my new proposal that is linked to this issue i will prepare a little util helper function that will simply allow to store values on change and listen for values also it will publish values on load you will to add that explicit for the values that need perserve of state

ViewModel: {
  todos: "any",
  connectedCallback(){
    Todo.getList({}).then( (todos) => {
      this.todos = todos;
    })
  }
}
ViewModel.todos.setValue(storeLocal('todos')) // Supply inital value if present in localStorage
VIewModel.todos.onChange(storeLocal('todos')) // Save value if changed

something like that i am not finished with the final api but i think you get the concept

@frank-dspeed
Copy link
Contributor

the guide for this should maybe show simply getter setter logic and value logic for preservingState some where

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

4 participants