React에서 localStorage를 사용하는 방법

71467 단어
나의 이전 문장에서 나는 이미 how to use react context for state management을 해석했다.이 강좌에서 로컬 저장소에 접근하여 응용 프로그램 상태를 저장하는 방법을 이해할 것입니다.
사용자의 이름을 입력할 수 있는 프로그램을 구축할 것입니다.
그리고 우리는 그들이 가장 좋아하는 과일을 선택하여 현지의 저장실에 보관하도록 할 것이다.
사용자가 다음에 이 페이지를 방문할 때, 우리는 그들이 가장 좋아하는 과일을 표시하고, 그들에게 과일을 바꾸는 옵션을 제공할 것이다.

프로젝트 작성


먼저 다음 명령을 사용하여 react 응용 프로그램을 만듭니다.
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에 저장된 이름을 볼 수 있습니다.

    디스플레이 옵션


    local Storage에 이름을 저장했기 때문에 과일 목록을 만들고 사용자에게 보여 드리겠습니다.
    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
    
    상기 코드에서
  • 우리는 로컬 메모리에서 사용자 데이터를 얻는데 이것은 우리가 데이터를 저장하는 방식과 매우 비슷하다.
    데이터는 문자열 형식으로 저장되기 때문에 자바스크립트 대상으로 변환합니다.
  • If you want to learn more about useEffect,
    I have written a comprehensive article on how to use useEffect in React

  • 저희가 두 지방주를 도입했습니다.
    하나는 사용자 데이터를 저장하고, 다른 하나는 editMode이라는 부울 값을 저장합니다.
    나중에 를 사용하여 디스플레이와 편집 화면 사이를 전환합니다.
  • formSubmitHandler 함수 중
  • ,
    사용자가 이름을 제출하면 편집 모드로 전환할 수 있도록 사용자 데이터와 editMode을 업데이트하고 있습니다.
  • 은 어플리케이션을 렌더링할 때 userDatanull인지 확인하고 있습니다. 즉, 사용자가 이 페이지를 처음 방문한 경우
    그리고 그들에게 이름을 제출하는 표를 보여 주어라. 그렇지 않으면 그들이 좋아하는 과일을 선택할 수 있다.
  • 우리는 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
    
    상기 코드에서
  • 즐겨찾기 폴더를 로컬 저장소에 저장하고 saveFavoriteseditMode으로 설정하는 함수를 추가했습니다.
  • 우리는 예쁜 작은 라벨에 가장 좋아하는 과일을 보여 줍니다.
  • 에서는 즐겨찾기 폴더를 업데이트하기 위해 편집 모드로 돌아가는 옵션도 제공합니다.
  • 만약 우리가 지금 프로그램을 실행하고 있다면, 가장 좋아하는 과일이localStorage에 저장되어 있는 것을 볼 수 있습니다.

    페이지를 새로 고치면 데이터가 지속되는 것을 볼 수 있습니다.

    useLocalStorage 연결 만들기


    로컬 스토리지를 여러 곳에서 액세스하고 있다는 사실을 이미 알고 계실 것입니다.
    갈고리를 만들면 파일로 분리해서 실용 함수로 사용할 수 있습니다.
    다음 코드를 사용하여 false이라는 폴더와 hooks이라는 파일을 만듭니다.
    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 데이터를 저장하고 초기화 기능을 제공합니다.
    전달된 키에 대응하는 값이 있는지 확인하십시오.
    있는 경우 로컬 스토리지의 데이터를 사용하여 상태를 초기화합니다.
    그렇지 않으면 이 값을 초기 값으로 설정하여 갈고리에 전달합니다.
  • 우리는 useLocalStorage.js 함수를 가지고 있으며 전달된 값이 리셋 함수인지 확인합니다.
    만약 그것이 리셋 함수라면, 기존 상태로 그것을 호출하고, 리셋 응답을 상태와 로컬 저장소로 업데이트합니다.
  • 마지막으로 우리는 setValuestate을 되돌려 setValue과 유사하게 연결했다.
  • 이제 useState에 새로 생성된 갈고리를 사용하겠습니다.
    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
    
    보시다시피 App.js을 사용하는 방식은 useLocalStorage 갈고리를 사용하는 방식과 유사합니다. useStateuseEffect을 제거했습니다.

    데모 및 소스 코드


    소스 코드 here
    데모 here을 참조하십시오.

    좋은 웹페이지 즐겨찾기