Description
(Moved from slightlyoff/history_api#21 by @StringEpsilon, summarized by me.)
Update vs. replace
The current proposal has appHistory.updateCurrentEntry({ state, url })
. Although it doesn't state so explicitly, the implication of this method name is that the same AppHistoryEntry
will have its state
and url
values updated. That is, it makes AppHistoryEntry
s mutable, at least when they are the current entry. Notably, the key
value would stay the same. Call this the "mutable history entry model".
An alternative approach would be to have appHistory.replaceCurrentEntry({ state, url })
. This would generate a new AppHistoryEntry
with the provided state
and url
. It would probably have a new key
(but see below). Call this the "immutable history entry model".
Also, note that the mutable model could have appHistory.replaceCurrentEntry()
as well as appHistory.updateCurrentEntry()
. Probably that would just be confusing, but it makes conceptual sense.
(For the record: window.history
takes a hybrid approach. The current window.history
history entry's state is mutable (via history.state
), but if you want to change the page's current URL, you need to replace the current history entry using history.replaceState()
.)
In general in programming, immutability can make things easier with less to worry about. That might be the case here, so I'm leaning toward switching to an immutable history entry model.
The meaning and uses of key
In @tbondwilkinson's work on creating nice application-level wrappers over window.history
, they have (at least) two keys:
- A "unique identifier" for the history entry, which is changed whenever the entry is replaced (i.e. whenever the URL of the entry changes). (Does it change if the state changes??)
- A "slot key" for the history entry, which stays stable even when the entry is replaced.
His apps use the slot key to navigate around, using the equivalent of appHistory.navigateTo(slotKey)
. Whereas the unique identifier is used to cache resources that are too big to store in state
, or to otherwise correlate a particular history entry with some out of band resource.
The app history proposal, with updateCurrentEntry()
, currently has only the "slot key". If we changed to the immutable history entry model, with replaceCurrentEntry()
, we could either:
- keep
key
as the slot key (so, the newAppHistoryEntry
would have the samekey
value as the old one), or - switch
key
to be a unique identifier (so, the newAppHistoryEntry
would generate a newkey
UUID).
We could also introduce both types of keys, or switch key
to be a unique identifier and introduce index
, or similar.
A potential issue with unique keys is that we need to define the behavior for what happens if you do something like
const uniqueKey = appHistory.currentEntry.key;
appHistory.replaceCurrentEntry();
appHistory.navigateTo(uniqueKey);
i.e. if you try to navigate to a key which is no longer in the current history entries list. I think we'd just fail, probably in the same way appHistory.back()
fails if you're at the beginning of the history list, or appHistory.navigateTo("non-existant-key")
fails.
Replacing and the old entry
If we did switch to an immutable history model with appHistory.replaceCurrentEntry()
, we could consider adding a feature like appHistory.currentEntry.replacedEntry
pointing to the now-replaced entry. This would extend indefinitely (?), so you could do appHistory.currentEntry.replacedEntry.replacedEntry
etc.
This also helps with the potential data loss, where calling replaceCurrentEntry()
, or updateCurrentEntry()
, will destroy any state
value you had there. On the other hand, maybe this sort of "data loss" is intentional, in that it's better not to use up memory and storage space on replaced entries. Hmm.