feat: track 'last online' time in localStorage#974
Conversation
| } | ||
| }, [online]) | ||
|
|
||
| return { online, offline: !online } |
There was a problem hiding this comment.
Should we return lastOnline in this hook?
// Only fetch if `online === false` as local storage is synchronous and disk-based
const lastOnline = !online ? localStorage.getItem(lastOnlineKey) : null
return {
online,
offline: !online,
lastOnline: lastOnline && new Date(lastOnline)
}Or have a separate useLastOnlineHook?
There was a problem hiding this comment.
oh yeah lol 🤦♂️
There was a problem hiding this comment.
I like adding it to this one 👍
There was a problem hiding this comment.
Interesting note: the way this is implemented currently using useEffect to set the lastOnline value in localStorage, that suggested code doesn't work to return the most recent lastOnline value from the hook because there isn't a rerender once the value in localStorage is changed. I'll have to refactor a bit to couple the localStorage change with the online state change so that the hook returns the most up-to-date lastOnline value, ideally without another rerender
There was a problem hiding this comment.
What about using the global store instead of local storage?
There was a problem hiding this comment.
Using the global store would be a useful part of 'Single online status provider' solution that Austin mentions below, but using just the global store alone wouldn't be able to track the status across sessions
There was a problem hiding this comment.
When useOnlineStatus is used potentially dozens of times across the app, this useEffect will run for each instance and update the localStorage at that time. This isn't practical and could maybe even cause race conditions / stale data / performance issues (localStorage is synchronous).
Instead, I would recommend setting this localStorage value only if the saved state is out of sync (i.e. if state is null when responding to type === 'offline', then and only then set the value to the last online time) in the debounced updateState callback. It should be read from localStorage in the render loop. (note there could possibly be performance implications from this on low-spec machines)
The best solution might be to implement a single global online/offline event handler which sets both the online status and the last online time in a global state provider (reading and writing to localStorage at that time) and which would then be consumed by the useOnlineStatus hook. This should reduce the possibility of race conditions. I realized that's a bit of a refactor though, might be something to look into in the future. It would also possibly allow for manually setting online/offline time from that central state handler in the future
|
Thanks for the feedback @amcgee! What you describe in the second paragraph sounds like the direction I was going with a refactor I mentioned above, and I pushed a change that I think implements what you describe -- did I understand you correctly?
I agree that a single handler/provider would be best and I think we should go for that in another iteration 👍 |
|
|
||
| return { online, offline: !online } | ||
| // Only fetch if `online === false` as local storage is synchronous and disk-based | ||
| const lastOnline = !online && localStorage.getItem(lastOnlineKey) |
There was a problem hiding this comment.
minor: useMemo might help mitigate possible performance issues here - without it any time the parent rerenders it might create a new options object and cause an unnecessary localStorage lookup - so long as we can assume the value of localStorage.getItem(lastOnlineKey) will never change once offline is set.
| const lastOnline = !online && localStorage.getItem(lastOnlineKey) | |
| const lastOnline = useMemo(() => !online && localStorage.getItem(lastOnlineKey), [online]) |
|
So here's something I noticed: if you're offline and open and app, and useEffect(() => {
if (!online && !localStorage.getItem('lastOnline')) {
localStorage.setItem(etc.)
}
}, [])but then I'm not sure what the most ideal way of updating the |
amcgee
left a comment
There was a problem hiding this comment.
Haven't tested but code looks good!
|
@KaiVandivier but what would we even set |
|
I was thinking just |
# [2.10.0](v2.9.2...v2.10.0) (2021-08-30) ### Features * track 'last online' time in localStorage ([#974](#974)) ([98d7cd3](98d7cd3))
|
🎉 This PR is included in version 2.10.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This feature can be used by apps or the header bar to display the 'last online' status. It's stored in
localStorageso that the value can persist between sessions and be used between apps (although it will only be updated in apps that use PWA or use the most recent UI with the new header bar).In the tests, I tried mocking the
Dateclass andDate.now(), but both approaches either had issues with typescript or would make the test fail for mysterious reasons :(