I wrote a cool hook! It’s a small wrapper around useState
which adds support for Meteor’s Reload package for data persistence, so that your data remains after refreshes during development and hot code push in production.
import { Meteor } from 'meteor/meteor'
import { Reload } from 'meteor/reload'
import { useState, useMemo, useEffect, SetStateAction, Dispatch } from 'react'
interface IHash {
[key: string] : any
}
if (Meteor.isClient) {
var toMigrate: IHash = {}
var migrated: IHash = Reload._migrationData('use-meteor-state') || {}
Reload._onMigrate('use-meteor-state', () => {
return [true, toMigrate]
})
}
interface IUseMeteorState {
<S>(initialValue: S | (() => S), name: string): [S, Dispatch<SetStateAction<S>>]
}
const useMeteorState: IUseMeteorState = (initialValue, name) => {
// When running in concurrent mode, this may run multiple times ...
useMemo(() => {
if (Meteor.isClient && migrated[name]) {
initialValue = migrated[name]
}
}, [name])
useEffect(() => {
// ... so cleanup happens only after the render is committed
if (migrated[name]) {
// move to toMigrate for next refresh
toMigrate[name] = migrated[name]
// remove migrated so lifecycle can do its thing
delete migrated[name]
}
return () => {
// Remove migration on unmount
if (toMigrate[name]) {
delete toMigrate[name]
}
}
}, [name])
const [value, setValue] = useState(initialValue)
return [value, (value) => {
toMigrate[name] = value
setValue(value)
}]
}
export default useMeteorState