useMeteorState - useState with data persistence

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

9 Likes

Will try it out ASAP. I’m wondering if this isn’t something that should be part of the official Metoer React package.

1 Like

I have this and a bunch of other hooks (mentioned on various forum posts) that I think should probably be part of an official package (or maybe set of packages). One important aspect of some of those is to move to the useMutableSource model for data retrieval from computations. That isn’t quite ready to share though.

3 Likes

One scenario I’m using it for is a search field and search results. I was trying to style up the search results, and every time I saved a file I’d have to rerun the search. Now each are stored using useMeteorState - the search field and the result set. So they persist between refreshes during development.

2 Likes

Can you share more of them. Let’s then make PR for each of them and discuss inclusion of them in the official packages.

Also the example is missing type for S.

1 Like

There is a PR with most of them in it - though I’ll probably break each one out to a separate PR when we merge for real. PR #298

My current plan is to get useFind released as part of react-meteor-data.

1 Like

BTW, these are mostly just waiting on tests and documentation to be written. The useMeteorData hook should be ready to go, as well as the accounts ones.

Even useFind is ready, it just needs documentation and tests.