Skip to content

Allows developers to add data to History.state #1658

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

Closed
zack24q opened this issue Aug 1, 2017 · 20 comments
Closed

Allows developers to add data to History.state #1658

zack24q opened this issue Aug 1, 2017 · 20 comments

Comments

@zack24q
Copy link

zack24q commented Aug 1, 2017

What problem does this feature solve?

Some data is expected to be stored along with the browsing history, but I do not want the data to appear in the URL, so I hope I can save data to History.state.

I am currently developing vue-navigation. To distinguish between different page instances of the same URL, I need to generate a unique key.

At present, key stored in the url, see demo, but in vue-router's history mode, I hope that the key is transparent to the user.

What does the proposed API look like?

Add state to route object, so the developer can choose to save the data to query or state.

router.push({ path: 'PATH', query: { VNK: 'VNK' }, state: { VNK: 'VNK' }})

next({ path: 'PATH', query: { VNK: 'VNK' }, state: { VNK: 'VNK' }})
@posva
Copy link
Member

posva commented Aug 1, 2017

Thanks for the proposal.
We're against passing the state invisibly in the url (params, query are ok). Instead, we prefer to use something like https://github.com/vuejs/vuex/

@posva posva closed this as completed Aug 1, 2017
@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

Maybe I expressed badly, I mean passing the state to History.state, not passing in url, like HTML5 pushState()method:

history.pushState({VNK: 'VNK'}, "TITLE", "TEST.html");

It will passing state to window.history, and even if user refresh the browser, state will be retained and corresponded to url one by one.

@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

for example: user's router is /index -> /list -> /index, when user refresh the browser , if no key in history's state, how do i distinguish between two /indexs? vuex also can't help me.

@LinusBorg
Copy link
Member

LinusBorg commented Aug 1, 2017

how do i distinguish

Distinguish in what way and what for? both will be the same route anyway?

@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

Because i want to distinguish the forward and backward behavior, if it is backward, i can restore page from cache, it is useful for mobile web app.

for example: user is in /list, if he forward to /index, the page will be new, if user backward to first /index, the page will restored from cache, it is like native app navigation.

so i add a key to distinguish the two route, they are not same.

I develop vue-navigation to do this, but now the key only can put in url, i against put the key in the url too, so i want put key in history.state, like vue-router does.https://github.com/vuejs/vue-router/blob/dev/src/util/push-state.js#L50

@posva
Copy link
Member

posva commented Aug 1, 2017

Your message was, I shouldn't have used the word url 😆 . The url is actually a piece of state
We don't want to associate state with vue-router outside of the url.

@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

Thanks for such a quick reply.

I still have some doubts, vue-router also added a key to statehttps://github.com/vuejs/vue-router/blob/dev/src/util/push-state.js#L50, I think this is to associate the URL with the ScrollPosition.

What is the difference with my opinion? I want to associate the url with the page cache.

@posva
Copy link
Member

posva commented Aug 1, 2017

Actually, nothing prevents you from using that key for page cache or something else

@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

But vue-router's key may be repeated, so I generated short UUID instead.

@zack24q
Copy link
Author

zack24q commented Aug 1, 2017

image
For example: user now in /list/3, the key is 2740, he refresh the browser, the key will not change, but the window.performance.now() will start from 0 again, so when user forward to /list/4,then to /list/5, then to /list/6, the key maybe repeated.

@joodo
Copy link

joodo commented Dec 24, 2017

And there is no way to get key in $route, so how to do if I want to save something like tab index, page number etc. in State bofore push?

@posva
Copy link
Member

posva commented Dec 24, 2017

use a query parameter, they are there for that: dashboard?pane=2&btcTab=1&currency=usd they allow you to save small pieces of state in the url. Otherwise, you can use what zack24q proposed above

@joodo
Copy link

joodo commented Dec 25, 2017

thanks, I'll try it

@hecktarzuli
Copy link

hecktarzuli commented May 4, 2018

So really the only way to re-hydrate using back/forward is to leverage Vuex, no way and no plans to ever have vue-router let us dump data into history like the native api?

@crswll
Copy link

crswll commented Jun 11, 2018

Is it safe to use the key from history.state? I'm thinking about tying this to some vuex state but want to make sure it's all right. I still think it would be really nice to have something like the native api has and keep some state in particular history entries.

@mistersender
Copy link

I would like to have the history state passed through as well. I have a situation wherein I'm using vue.js alongside a separate application, which uses the history state for some other things. However, because vue.js does not have access to the history state, i am limited by how i am able to reroute calls. I want to be able to use beforeEach on the vue-router to sniff for the presence of specific history state elements (again, not coming from my vue app), and route differently in those cases. As it stands now, i am doing some very hacky workarounds that only mostly work.

@darklow
Copy link

darklow commented Jul 27, 2018

This would be very useful. I have very simple scenario:

Imagine two categories of news items: Top News and Latest news, one is accessible through /news/top another through /news/latest. When you choose specific news item, it goes to route with url /news/[ID]/. Now when you are navigating back, I can no longer tell which news post was viewed from which list. You may say I should add extra param in URL like /news/[ID]/?tab=latest however there is a big problem, if I do that I can no longer use browser built in history tracking and use :visited CSS selector as browser treats those as two separate URLs even with using anchors like /news/[ID]/#latest or /news/[ID]/#top.

If I could store extra data to each location change I could add the current tab which news item was opened from. I tried to do it now, but it is very difficult to implement without having some kind of unique router step identification as same news item may appear multiple times in one user session.

So currently I haven't found any workaround.

@jnields
Copy link

jnields commented Sep 6, 2018

@posva it is often desirable to not use a query parameter. A lot of UI state I don't want to keep in the URL. Query params are basically forever - once they're in use you'll have links to your site with them everywhere.

Putting something like "user inputed text" or "selected colors" or "open accordions" in query params means that bookmarking that page will restore that. It also means you need to support those query params for much longer than the cycle of UI changes is likely to be.

I do want to have state saved for locations, though. So where to put it?

history.state is a very appropriate place.

Vuex doesn't solve this issue. history.state could be used to restore a Vuex store's previous state for a given location, however.

@JulianGaibler
Copy link

I know this issue is two years old, but I thought in case someone stumbled upon this again, I could offer my workaround.

I use replaceState from the history API when the user leaves...

beforeRouteLeave(to, from, next) {
    history.replaceState({
        ...window.history.state,
        search: this.search,
    }, '')
    next()
}

...and then retrieve it once the component mounts again.

beforeMount() {
    if (window.history.state.search) {
        this.search = window.history.state.search
    }
},

@posva
Copy link
Member

posva commented Oct 1, 2019

Locking as discussion is at #2243

@vuejs vuejs locked as resolved and limited conversation to collaborators Oct 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants