🍑

localStrage に保管しながら useState を利用する

2021/08/14に公開

概要

useState でリアクティブな値を使いたい。useState はリロードすると値が消えてしまう。リロードしても値を消したくない。localStageを併用して解決しよう。

localStrage に拡張した useState

useState の感覚で利用でき、 localStrage にも値を残せる。

import { useState } from 'react'
export const usePersist = (_key: string, initValue: any) => {
  const key = 'hooks:' + _key
  const value = () => {
    try {
      const item = window.localStorage.getItem(key)
      return item ? JSON.parse(item) : initValue
    } catch (error) {
      console.log(error)
      return initValue
    }
  }
  const setValue = (value: any) => {
    try {
      setSavedValue(value)
      window.localStorage.setItem(key, JSON.stringify(value))
    } catch (error) {
      console.log(error)
    }
  }
  const [savedValue, setSavedValue] = useState(value)
  return [savedValue, setValue]
}

利用例

import { useState } from 'react'
import { usePersist } from '../compositions/usePersist'

export const AlertMessagePersist = () => {
  const [mydata, setMydata] = usePersist('mydata', null)
  const [name, setName] = useState(mydata?.name || '')
  const onChangeName = (
    element: React.ChangeEvent<HTMLInputElement> | undefined
  ) => {
    if (element === undefined) return
    setName(element.target.value)
  }
  const onAction = () => {
    const data = {
      name,
    }
    setMydata(data)
  }

  return (
    <div className="alert alert-primary h5 text-primary">
      <h5 className="mb-4">{JSON.stringify(mydata)}</h5>
      <div className="form-group">
        <label htmlFor="" className="h6">
          Name
        </label>
        <input
          type="text"
          onChange={onChangeName}
          value={name}
          className="form-control"
        />
      </div>
      <div className="form-group">
        <button className="btn btn-primary" onClick={onAction}>
          save
        </button>
      </div>
    </div>
  )
}

Discussion