LocalStorageを使用する方法

71393 ワード

私の前の記事の1つで、私は説明しましたhow to use react context for state management . このチュートリアルでは、ローカルストレージにアクセスする方法を参照し、アプリケーションの状態を格納するために使用します.
ユーザー名を入力するアプリケーションを構築します.
それから、我々は彼らに彼らの大好きな果物を選んで、ローカル記憶装置で彼らを保存するよう頼みます.
ユーザーが次回ページを訪問すると、私たちは自分の好きな果物を表示し、それらを変更するオプションを提供します.

プロジェクトの設定


まず、次のコマンドを使って反応アプリを作成しましょう.
npx create-react-app react-local-storage
私たちはBluePrintJS 申し込む
それで、我々はスタイリング部分について心配する必要はありません、そして、我々は論理に集中することができます.
BluePrintjsをインストールするには、次のコマンドを実行します.
yarn add @blueprintjs/core
では、BluePrintjsに関連するスタイルシートファイルをindex.css また、いくつかの基本的なスタイルを追加します.
@import "~normalize.css";
@import "~@blueprintjs/core/lib/css/blueprint.css";
@import "~@blueprintjs/icons/lib/css/blueprint-icons.css";

body {
  margin: 10px auto;
  max-width: 400px;
}
.space {
  margin: 5px 5px 10px 5px;
}

アプリのビルド


アプリで.JS入力ボタンを入力して名前と送信ボタンを入力します.
import { Button, Card, FormGroup, InputGroup } from "@blueprintjs/core"
import { useState } from "react"

function App() {
  const [name, setName] = useState("")

  const formSubmitHandler = e => {
    e.preventDefault()
  }
  return (
    <div>
      <Card elevation="1">
        <form onSubmit={formSubmitHandler}>
          <FormGroup label="Name" labelFor="name">
            <InputGroup
              id="Name"
              placeholder="Name"
              type="Name"
              value={name}
              onChange={e => setName(e.target.value)}
            />
          </FormGroup>
          <Button intent="primary" text="Submit" fill type="submit" />
        </form>
      </Card>
    </div>
  )
}

export default App
ここでは、ローカルストレージに名前を格納し、フォームを送信するときには何もしていません.
名前をローカルストレージに保存しましょうformSubmitHandler 機能
const formSubmitHandler = e => {
  e.preventDefault()
  try {
    window.localStorage.setItem("user", JSON.stringify({ name, favorites: [] }))
  } catch (error) {
    console.log(error)
  }
}
こちらです.
  • ローカルストレージが文字列値のみを格納できるため、JavaScriptオブジェクトを文字列に変換します.
  • また、空の配列をfavorites , ユーザーの好みの果物を保存するために後で使用されます.
  • LocalStorageにアクセスすると例外が発生する可能性がありますので、try catchブロック内でコードを同封します
    LocalStorageがサポートされていないか、ユーザーがアクセスをブロックしている場合.
  • アプリケーションを実行してフォームを送信すると、ローカルストレージに保存されている名前が表示されます.

    オプションの表示


    localstorageに名前を保存したので、果物のリストを持って、それをユーザーに表示しましょう.
    import {
      Button,
      Card,
      Checkbox,
      FormGroup,
      InputGroup,
    } from "@blueprintjs/core"
    import { useEffect, useState } from "react"
    
    const fruits = [
      "Apple",
      "Orange",
      "Guava",
      "Mango",
      "Grapes",
      "Kiwi",
      "Strawberry",
    ]
    
    function App() {
      const [name, setName] = useState("")
      const [userData, setUserData] = useState()
      const [editMode, setEditMode] = useState(false)
    
      useEffect(() => {
        // Fetch the user data from the localStorage and set it to the local state userData
        try {
          const user = window.localStorage.getItem("user")
    
          if (!user) {
            setUserData(null)
          } else {
            const parsedData = JSON.parse(user)
            setUserData(parsedData)
            if (parsedData.favorites.length === 0) {
              setEditMode(true)
            }
          }
        } catch (error) {
          console.log(error)
          setUserData(null)
        }
      }, [])
    
      const onFruitChecked = (e, fruit) => {
        // Check if the fruit exists in the current list of favorites
        const index = userData.favorites.indexOf(fruit)
        // If the checkbox is checked and fruit is not part of favorites
        if (e.target.checked && index === -1) {
          setUserData(prevValues => {
            // Add the fruit to the current list of favorites
            return { ...prevValues, favorites: [...prevValues.favorites, fruit] }
          })
        } else if (!e.target.checked && index !== -1) {
          // If the checkbox is unchecked and fruit is part of favorites
          setUserData(prevValues => {
            // Remove the fruit from the current list of favorites
            return {
              ...prevValues,
              favorites: [
                ...prevValues.favorites.slice(0, index),
                ...prevValues.favorites.slice(index + 1),
              ],
            }
          })
        }
      }
    
      const formSubmitHandler = e => {
        e.preventDefault()
        try {
          setUserData({ name, favorites: [] })
          setEditMode(true)
          window.localStorage.setItem(
            "user",
            JSON.stringify({ name, favorites: [] })
          )
        } catch (error) {
          console.log(error)
        }
      }
    
      return (
        <div>
          {userData === null && (
            <Card elevation="1">
              <form onSubmit={formSubmitHandler}>
                <FormGroup label="Name" labelFor="name">
                  <InputGroup
                    id="Name"
                    placeholder="Name"
                    type="Name"
                    value={name}
                    onChange={e => setName(e.target.value)}
                  />
                </FormGroup>
                <Button intent="primary" text="Submit" fill type="submit" />
              </form>
            </Card>
          )}
          {userData && editMode && (
            <Card elevation="1">
              <p>
                Welcome <strong>{userData.name}</strong>, choose your favorite
                fruits:
              </p>
              {fruits.map(fruit => {
                return (
                  <Checkbox
                    key={fruit}
                    label={fruit}
                    inline={true}
                    className="space"
                    checked={userData.favorites.indexOf(fruit) !== -1}
                    onChange={e => {
                      onFruitChecked(e, fruit)
                    }}
                  />
                )
              })}
              <Button intent="primary" text="Save" fill type="submit" />
            </Card>
          )}
        </div>
      )
    }
    
    export default App
    
    上のコードで
  • ローカルストレージからユーザーデータを取得する効果があります.
    データは文字列形式で格納されているので、JavaScriptオブジェクトに変換します.
  • If you want to learn more about useEffect,
    I have written a comprehensive article on how to use useEffect in React

  • 我々は2つの追加のローカル州を導入している.
    ユーザデータを格納するものともう一つのブール値を格納するものeditMode ,
    これは後でディスプレイと編集画面の間をトグルするために使用されます.
  • formSubmitHandler 機能
    我々は、ユーザーデータを更新しているeditMode ユーザーが自分の名前を送信すると、ユーザーが編集モードに切り替えられるようにします.
  • アプリケーションのレンダリング中にuserData is null , すなわち、ユーザが初めてページを訪問している場合、
    その後、彼らはそれ以外の場合は、自分の好きな果物を選択することができます名前を提出するフォームを表示します.
  • 私達は関数と呼ばれるonFruitChecked , ユーザーがチェックしたり、チェックしたりするときに、現在選択されているお気に入りの果物を更新します.
  • 次に、アプリケーションを実行すると、次のようにオプションが表示されます.

    選択肢の保存と表示


    今、我々はユーザーの選択を選択したuserData.favorites 配列.ローカルストレージに保存しましょう.
    import {
      Button,
      Card,
      Checkbox,
      FormGroup,
      InputGroup,
      Tag,
    } from "@blueprintjs/core"
    import { useEffect, useState } from "react"
    
    const fruits = [
      "Apple",
      "Orange",
      "Guava",
      "Mango",
      "Grapes",
      "Kiwi",
      "Strawberry",
    ]
    
    function App() {
      const [name, setName] = useState("")
      const [userData, setUserData] = useState()
      const [editMode, setEditMode] = useState(false)
    
      useEffect(() => {
        // Fetch the user data from the localStorage and set it to the local state userData
        try {
          const user = window.localStorage.getItem("user")
    
          if (!user) {
            setUserData(null)
          } else {
            const parsedData = JSON.parse(user)
            setUserData(parsedData)
            if (parsedData.favorites.length === 0) {
              setEditMode(true)
            }
          }
        } catch (error) {
          console.log(error)
          setUserData(null)
        }
      }, [])
    
      const onFruitChecked = (e, fruit) => {
        // Check if the fruit exists in the current list of favorites
        const index = userData.favorites.indexOf(fruit)
        // If the checkbox is checked and fruit is not part of favorites
        if (e.target.checked && index === -1) {
          setUserData(prevValues => {
            // Add the fruit to the current list of favorites
            return { ...prevValues, favorites: [...prevValues.favorites, fruit] }
          })
        } else if (!e.target.checked && index !== -1) {
          // If the checkbox is unchecked and fruit is part of favorites
          setUserData(prevValues => {
            // Remove the fruit from the current list of favorites
            return {
              ...prevValues,
              favorites: [
                ...prevValues.favorites.slice(0, index),
                ...prevValues.favorites.slice(index + 1),
              ],
            }
          })
        }
      }
    
      const formSubmitHandler = e => {
        e.preventDefault()
        try {
          setUserData({ name, favorites: [] })
          setEditMode(true)
          window.localStorage.setItem(
            "user",
            JSON.stringify({ name, favorites: [] })
          )
        } catch (error) {
          console.log(error)
        }
      }
    
      const saveFavorites = () => {
        try {
          window.localStorage.setItem("user", JSON.stringify(userData))
          setEditMode(false)
        } catch (error) {
          console.log(error)
        }
      }
    
      return (
        <div>
          {userData === null && (
            <Card elevation="1">
              <form onSubmit={formSubmitHandler}>
                <FormGroup label="Name" labelFor="name">
                  <InputGroup
                    id="Name"
                    placeholder="Name"
                    type="Name"
                    value={name}
                    onChange={e => setName(e.target.value)}
                  />
                </FormGroup>
                <Button intent="primary" text="Submit" fill type="submit" />
              </form>
            </Card>
          )}
          {userData &&
            (editMode ? (
              <Card elevation="1">
                <p>
                  Welcome <strong>{userData.name}</strong>, choose your favorite
                  fruits:
                </p>
                {fruits.map(fruit => {
                  return (
                    <Checkbox
                      key={fruit}
                      label={fruit}
                      inline={true}
                      className="space"
                      checked={userData.favorites.indexOf(fruit) !== -1}
                      onChange={e => {
                        onFruitChecked(e, fruit)
                      }}
                    />
                  )
                })}
                <Button
                  intent="primary"
                  text="Save"
                  fill
                  type="submit"
                  onClick={saveFavorites}
                />
              </Card>
            ) : (
              <Card elevation="1">
                <p>
                  Welcome <strong>{userData.name}</strong>, your favorite fruits
                  are:
                </p>
                {userData.favorites.map(fruit => {
                  return (
                    <Tag
                      key={fruit}
                      round
                      minimal
                      large
                      intent="success"
                      className="space"
                    >
                      {fruit}
                    </Tag>
                  )
                })}
                <Button
                  intent="primary"
                  text="Change"
                  fill
                  type="submit"
                  onClick={() => setEditMode(true)}
                />
              </Card>
            ))}
        </div>
      )
    }
    
    export default App
    
    上のコードで
  • という関数を追加しましたsaveFavorites , この関数は、お気に入りをlocalstorageに保存し、editMode to false .
  • 我々は良い小さなタグの中に好きな果物を表示している.
  • また、お気に入りを更新するには、モードを編集するに戻るオプションを与えている.
  • 我々は現在、アプリケーションを実行する場合は、お好みの果物がlocalstorageに保存されて表示されます.

    ページを再表示すると、データが永続化されます.

    uselocalstorageフックの作成


    複数の場所でローカルストレージにアクセスしていることがわかりました.
    私たちがファイルにそれを切り離すことができて、ユーティリティ機能として機能することができるように、フックを作成しましょう.
    フォルダを作成するhooks と呼ばれるファイルuseLocalStorage.js 次のコードを入力します.
    import { useState } from "react"
    
    const useLocalStorage = (key, initialValue) => {
      const [state, setState] = useState(() => {
        // Initialize the state
        try {
          const value = window.localStorage.getItem(key)
          // Check if the local storage already has any values,
          // otherwise initialize it with the passed initialValue
          return value ? JSON.parse(value) : initialValue
        } catch (error) {
          console.log(error)
        }
      })
    
      const setValue = value => {
        try {
          // If the passed value is a callback function,
          //  then call it with the existing state.
          const valueToStore = value instanceof Function ? value(state) : value
          window.localStorage.setItem(key, JSON.stringify(valueToStore))
          setState(value)
        } catch (error) {
          console.log(error)
        }
      }
    
      return [state, setValue]
    }
    
    export default useLocalStorage
    
    上記のフックで
  • LocalStorageデータを格納するローカル状態があり、初期化機能を持ちます.
    を返します.
    それが存在するならば、それはローカル記憶からデータで状態を初期化します.
    さもなければ、それは初期値に値をセットします.
  • 我々はsetValue 関数は、渡された値がコールバック関数であるかどうかを調べます.
    コールバック関数であれば、既存の状態を呼び出し、コールバックの応答を状態とlocalstorageに更新します.
  • 最後に、両方ともstate だけでなくsetValue , と同様であるuseState フック.
  • では、新しく作成されたフックを使用しましょうApp.js :
    import {
      Button,
      Card,
      Checkbox,
      FormGroup,
      InputGroup,
      Tag,
    } from "@blueprintjs/core"
    import { useState } from "react"
    import useLocalStorage from "./hooks/useLocalStorage"
    
    const fruits = [
      "Apple",
      "Orange",
      "Guava",
      "Mango",
      "Grapes",
      "Kiwi",
      "Strawberry",
    ]
    
    function App() {
      const [name, setName] = useState("")
      const [userData, setUserData] = useLocalStorage("user", null)
      // Set edit mode to true whenever the userData is not present or
      // selected favorites are 0
      const [editMode, setEditMode] = useState(
        userData === null || userData?.favorites?.length === 0
      )
    
      const onFruitChecked = (e, fruit) => {
        // Check if the fruit exists in the current list of favorites
        const index = userData.favorites.indexOf(fruit)
        // If the checkbox is checked and fruit is not part of favorites
        if (e.target.checked && index === -1) {
          setUserData(prevValues => {
            // Add the fruit to the current list of favorites
            return { ...prevValues, favorites: [...prevValues.favorites, fruit] }
          })
        } else if (!e.target.checked && index !== -1) {
          // If the checkbox is unchecked and fruit is part of favorites
          setUserData(prevValues => {
            // Remove the fruit from the current list of favorites
            return {
              ...prevValues,
              favorites: [
                ...prevValues.favorites.slice(0, index),
                ...prevValues.favorites.slice(index + 1),
              ],
            }
          })
        }
      }
    
      const formSubmitHandler = e => {
        e.preventDefault()
        try {
          setUserData({ name, favorites: [] })
          setEditMode(true)
        } catch (error) {
          console.log(error)
        }
      }
    
      return (
        <div>
          {userData === null && (
            <Card elevation="1">
              <form onSubmit={formSubmitHandler}>
                <FormGroup label="Name" labelFor="name">
                  <InputGroup
                    id="Name"
                    placeholder="Name"
                    type="Name"
                    value={name}
                    onChange={e => setName(e.target.value)}
                  />
                </FormGroup>
                <Button intent="primary" text="Submit" fill type="submit" />
              </form>
            </Card>
          )}
          {userData &&
            (editMode ? (
              <Card elevation="1">
                <p>
                  Welcome <strong>{userData.name}</strong>, choose your favorite
                  fruits:
                </p>
                {fruits.map(fruit => {
                  return (
                    <Checkbox
                      key={fruit}
                      label={fruit}
                      inline={true}
                      className="space"
                      checked={userData.favorites.indexOf(fruit) !== -1}
                      onChange={e => {
                        onFruitChecked(e, fruit)
                      }}
                    />
                  )
                })}
                <Button
                  intent="primary"
                  text="Done"
                  fill
                  type="submit"
                  onClick={() => setEditMode(false)}
                />
              </Card>
            ) : (
              <Card elevation="1">
                <p>
                  Welcome <strong>{userData.name}</strong>, your favorite fruits
                  are:
                </p>
                {userData.favorites.map(fruit => {
                  return (
                    <Tag
                      key={fruit}
                      round
                      minimal
                      large
                      intent="success"
                      className="space"
                    >
                      {fruit}
                    </Tag>
                  )
                })}
                <Button
                  intent="primary"
                  text="Change"
                  fill
                  type="submit"
                  onClick={() => setEditMode(true)}
                />
              </Card>
            ))}
        </div>
      )
    }
    
    export default App
    
    ご覧のように、我々はuseLocalStorage 同じようにuseState フックと我々はuseEffect and saveFavorites (チェックボックス自体をチェックすると、それはlocalstorageに保存されます).

    デモとソースコード


    ソースコードをダウンロードできますhere and
    デモを見るhere .