react-native-mmkv icon indicating copy to clipboard operation
react-native-mmkv copied to clipboard

Settings a `false` value is equivalent to delete

Open maximilize opened this issue 2 years ago • 7 comments

When settings a value which is false, the next getBoolean operation will return undefined.

maximilize avatar Oct 21 '22 17:10 maximilize

Huh? Are you sure? I think I tested that... On iOS or Android or both?

mrousavy avatar Oct 24 '22 10:10 mrousavy

I only tested it on Android so far.

maximilize avatar Nov 09 '22 21:11 maximilize

I can confirm this happens. Whenever we try to set the value to false, next get operation will return undefined.

"react-native-mmkv": "2.5.1", "react-native": "0.65.2".

Tested on Android.

krutarth-h-dave avatar Jan 30 '23 17:01 krutarth-h-dave

Hmm, this is weird, maybe there is some casting going on? Can this be reproduced in the example app?

mrousavy avatar Jan 30 '23 18:01 mrousavy

I think this happens with -1 as well using getNumber its undefined

ChARCOOL avatar Feb 03 '23 15:02 ChARCOOL

I think I found the problem in my case.

I was using mmkv like this.

export default function useStorage<T>(storageKey: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    const storedValue = storage.getString(storageKey)
    return storedValue ? JSON.parse(storedValue) : initialValue
  })

  const setValue = useCallback(
    (value: T) => {
      setStoredValue(value)
      storage.set(storageKey, JSON.stringify(value))
    },
    [storageKey]
  )

  return { value: storedValue, setValue }
}

I was stringifying all the values while setting and parsing them while getting. However, when I set -1 as a string "-1", it was deleting the value and I was getting undefined on the next call to get.

Changing it like this fixed it for me.

export default function useStorage<T>(storageKey: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    if (typeof initialValue === 'number') {
      return storage.getNumber(storageKey) ?? initialValue
    }

    if (typeof initialValue === 'boolean') {
      return storage.getBoolean(storageKey) ?? initialValue
    }

    const value = storage.getString(storageKey)
    return value ? JSON.parse(value) : initialValue
  })

  const setValue = useCallback(
    (value: T) => {
      if (typeof value === 'number' || typeof value === 'boolean') {
        storage.set(storageKey, value)
        setStoredValue(value)
        return
      }

      storage.set(storageKey, JSON.stringify(value))
      setStoredValue(value)
    },
    [storageKey]
  )

  return { value: storedValue, setValue }
}

ChARCOOL avatar Feb 03 '23 17:02 ChARCOOL

Hey! Does this problem still persist? Is the code you posted the reproduceable example?

mrousavy avatar Jul 17 '23 11:07 mrousavy

Hey - I think this has been fixed in V3 beta.

mrousavy avatar Jul 22 '24 15:07 mrousavy