재사용 가능한 로컬 저장 연결을 만드는 방법

안녕, 세상.👋


갈고리는 React의 특수한 형식의 함수로 React 기능 구성 요소에서 호출할 수 있습니다.그것들은 당신에게 데이터를 저장하고 상호작용을 증가시키며 이른바 부작용을 수행할 수 있다.
가장 흔히 볼 수 있는 연결고리는 다음과 같다.
  • 사용 상태
  • 사용 효과
  • 사용자 EF
  • 컨텍스트 사용
  • 사용자 교육자
  • 지난 글React Hooks: Managing State With useState Hook에서 우리는 useStatehook를 이해했다.우리는 본고에서 useState 갈고리를 사용할 것입니다. 따라서 만약 당신이 이전 갈고리를 읽지 않았다면, 읽기 전에 먼저 그것을 읽으십시오.본고에서 우리는 useEffect 갈고리를 배운 후에 그것을 사용하여 사용자 정의적이고 다시 사용할 수 있는 로컬 저장 갈고리를 구축할 것이다.

    사용 효과

    useEffect는 React의 내장 함수입니다.그것은 어떤 내용도 되돌려주지 않고 리셋 함수를 매개 변수로 한다.
    예:
    useEffect(() => {
        //...do something here
    })
    
    주:
  • React는 구성 요소의 렌더링 및 재렌더링 후 실행useEffect에 존재하는 리셋입니다.
  • 재사용 가능한 로컬 저장소 연결 만들기


    간단한 사용 효과


    간단한 counter 예시를 들읍시다. 아래와 같습니다.
    function Counter() {
      const [count, setCount] = useState(0);
      const incrementCount = () => {
        setCount(count + 1);
      };
      return <button onClick={incrementCount}>{count}</button>;
    }
    
    상기 샌드박스의 계수기를 추가하고 샌드박스 페이지를 다시 불러오십시오.페이지를 다시 불러오기만 하면 카운터가 0으로 초기화됩니다.만약 우리가 그러고 싶지 않다면.우리는 카운터가 샌드박스 페이지를 다시 불러온 후에도 같은 값을 유지하기를 바란다.한 가지 방법은 카운터의 값을 로컬 메모리에 저장하고 다시 불러올 때 그곳에서 카운터 상태를 동기화하는 것이다.
    이 점을 어떻게 사용하는지 봅시다useEffect.
    useEffect(() => {
        localStorage.setItem('count', count)
    })
    
    이렇게 하는 목적은 구성 요소가 다시 시작될 때마다 로컬 저장소 count 키의 값을 업데이트하는 것이다.
    function Counter() {
      const [count, setCount] = useState(0);
      const incrementCount = () => {
        setCount(count + 1);
      };
      useEffect(() => {
        localStorage.setItem('count', count)
      })
      return <button onClick={incrementCount}>{count}</button>;
    }
    

    계수가 증가함에 따라 localStorage의 계수가 증가하는 것을 볼 수 있습니다.그러나 페이지에 다시 로그인하면 로컬 스토리지에서도 계수가 0으로 재설정됩니다.이것은 우리가 localStorage에서 초기 값을 얻지 못했기 때문이다count.
    localstorage에서 초기 값을 가져오기 위해 구성 요소를 변경합니다.
    function Counter() {
      const [count, setCount] = useState(() => localStorage.getItem('count') || 0);
      const incrementCount = () => {
        setCount(count + 1);
      };
      useEffect(() => {
        localStorage.setItem('count', count)
      })
      return <button onClick={incrementCount}>{count}</button>;
    }
    
    주:
    여기서 우리는 지금 lazy initialization의 상태를 만들고 있다.
    계수를 늘리고 샌드박스를 다시 불러오십시오.카운터가 더 이상 0으로 재설정되지 않는 것을 볼 수 있습니다.그러나 우리는 새로운 문제에 직면해 있다.
    문제를 재현하기 위해
  • 계수를 몇 번 증가시킵니다.
  • 페이지를 다시 로드합니다.
  • 이제 계수 버튼을 클릭하여 계수를 다시 추가합니다.
  • 계수는 1이 아니라 기존 계수에 연결되는 것을 보실 수 있습니다.
  • 이것은 localStorage가 값을 저장하는 방식 때문입니다.모든 내용을 문자열 형식으로 저장합니다.따라서 로컬스토리지에 숫자를 저장하려고 해도 문자열로 변환해서 저장합니다.따라서 localStorage에서 값을 얻을 때 숫자가 아닌 문자열을 얻습니다.이것이 바로 계수를 늘리는 행위가 제대로 효과를 거두지 못한 이유다.
    우리 이 문제를 해결해 봅시다.
    function convertNumberToString(num) {
      return `${num}`
    }
    
    function convertStringToNumber(str) {
      return Number(str)
    }
    
    function getInitialValue() {
      const localStorageValue = localStorage.getItem('count')
    
      // here we are converting the string in localStorage to number before returning
      return convertStringToNumber(localStorageValue) || 0
    }
    
    function Counter() {
      const [count, setCount] = useState(() => getInitialValue());
      const incrementCount = () => {
        setCount(count + 1);
      };
      useEffect(() => {
        // we are converting the number to string before storing in localStorage
        // This way, we can control how the conversion happens
        localStorage.setItem('count', convertNumberToString(count))
      })
      return <button onClick={incrementCount}>{count}</button>;
    }
    
    이제 모든 것이 정상인 것 같다.그러나 우리는 더욱 최적화할 수 있다.

    종속성 배열


    useEffect에 콘솔 로그를 추가하고 언제 실행되는지 확인하십시오.
    useEffect(() => {
        console.log('useEffect callback is getting executed')
        localStorage.setItem('count', convertNumberToString(count))
    })
    
    구성 요소가 다시 렌더링될 때마다 useEffect 콜백이 실행됩니다.'다른 상태 업데이트'단추를 눌러 보세요.계수에 변화가 없어도 호출됩니다 useEffect.이것은 예기한 행위다.그러나, 우리는 count의 값이 변경될 때만 localStorage에서 이 값을 설정하기를 희망합니다.
    React는 이를 실현하는 방법을 제공합니다.useEffect는 수조를 두 번째 매개 변수로 한다.그것은 dependency array 라고 불린다.이 그룹에 의존하는 모든 의존 항목을 지정할 수 있습니다.useEffect 리셋은 이 의존 항목 중 하나에 변화가 발생할 때만 실행됩니다.
    예를 들어, 우리는 예시의 useEffect 가 계수 변경 시에만 실행되기를 희망한다.당신은 다음과 같은 방식으로 이 점을 실현할 수 있습니다.
    useEffect(() => {
        console.log('useEffect callback is getting executed')
        localStorage.setItem('count', convertNumberToString(count))
    }, [count])
    
    현재 다른 상태 업데이트를 누르면 구성 요소가 다시 시작되지만 useEffect 리셋은 실행되지 않습니다.
    우리 모든 것을 함께 놓자.
    import React, { useState, useEffect } from "react";
    
    function convertNumberToString(num) {
        return `${num}`;
    }
    
    function convertStringToNumber(str) {
        return Number(str);
    }
    
    function getInitialValue() {
        const localStorageValue = localStorage.getItem("count");
        return convertStringToNumber(localStorageValue) || 0;
    }
    
    function Counter() {
        const [count, setCount] = useState(() => getInitialValue());
        const incrementCount = () => {
            setCount(count + 1);
        };
        useEffect(() => {
            localStorage.setItem("count", convertNumberToString(count));
        }, [count]);
        return (
            <button className="btn" onClick={incrementCount}>
                {count}
            </button>
        );
    }
    
    export default Counter;
    

    재사용 가능한 연결 만들기


    The useLocalStorageState hook example shown here is based on the example from Kent C. Dodds's EpicReact.Dev React Hooks workshop.


    많은 곳에서 localStorage에 저장된 상태의 같은 논리가 필요할 수 있기 때문에, 사용자 정의 갈고리를 만들어서 이 동작을 실행할 수 있으며, localStorage에 저장된 상태를 필요로 하는 모든 곳에서 사용할 수 있습니다.
    function convertNumberToString(num) {
        return `${num}`;
    }
    
    function convertStringToNumber(str) {
        return Number(str);
    }
    
    function getInitialValue() {
        const localStorageValue = localStorage.getItem("count");
        return convertStringToNumber(localStorageValue) || 0;
    }
    
    function useLocalStorageState() {
        const [count, setCount] = useState(() => getInitialValue());
        const incrementCount = () => {
            setCount(count + 1);
        };
        useEffect(() => {
            localStorage.setItem("count", convertNumberToString(count));
        }, [count]);
        return [count, setCount]
    }
    
    이것이 바로 우리가 현재 가지고 있는 것이다.상황을 개괄하기 위해 재구성합시다.
    function getInitialValue(key, defaultValue, convertFromString) {
      const localStorageValue = localStorage.getItem(key);
      return convertFromString(localStorageValue) || defaultValue;
    }
    function useLocalStorageState(
      key,
      defaultValue = "",
      { convertToString = JSON.stringify, convertFromString = JSON.parse } = {}
    ) {
      const [state, setState] = useState(() =>
        getInitialValue(key, defaultValue, convertFromString)
      );
    
      useEffect(() => {
        localStorage.setItem(key, convertToString(state));
      }, [key, state, convertToString]);
    
      return [state, setState];
    }
    
    우리 여기서 뭐 했어?
  • 변수 useEffectcountsetCountstate 로 변경합니다.
  • 우리는 사용자에게 setState 을 매개 변수로 제공할 것을 요구합니다.우리는 상태를 local Storage의 이 키에 저장할 것이다.
  • 사용자에게도 초기 기본값을 매개 변수로 전달해야 합니다.이전에 우리의 예시에서 그것은 0이었다.
  • 우리는 사용자가 선택적으로 keyconvertToString 함수를 매개 변수로 전달할 것을 요구한다.
  • 사용자가 제공하지 않으면 기본값은 convertFromStringJSON.stringify 입니다.
  • 우리는 JSON.parse 의존 항목 그룹을 업데이트하고 모든 의존 항목을 추가했습니다.
  • 마지막으로 우리는 수조의 형식으로 useEffectstate를 되돌려줍니다. 내장useState 갈고리가 수조를 되돌려주는 방식과 유사합니다.
  • 이 사용자 정의 연결을 사용하는 예시를 변경합니다.
    function Counter() {
        const [count, setCount] = useLocalStorageHook('count', 0);
        const incrementCount = () => {
            setCount(count + 1);
        };
        return (
            <button className="btn" onClick={incrementCount}>
                {count}
            </button>
        );
    }
    
    사용자도 usestate의 작업 방식과 유사한 함수를 초기 값으로 전달할 수 있도록 할 수 있습니다.
    function getInitialValue(key, defaultValue, convertFromString) {
      const localStorageValue = localStorage.getItem(key);
    
     // change starts here
      if(localStorageValue) {
        return convertFromString(localStorageValue)
      }
      return typeof defaultValue === 'function' ? defaultValue() : defaultValue
     // change ends here
    }
    
    때때로 로컬 메모리에 주어진 키에 대한 값이 존재하면 useState 함수가 오류를 일으킬 수 있습니다.이 경우 새 값을 추가하기 전에 로컬 저장소에서 해당하는 키 값 쌍을 삭제할 수 있습니다.
    function getInitialValue(key, defaultValue, convertFromString) {
      const localStorageValue = localStorage.getItem(key);
    
      if(localStorageValue) {
        // change starts here
        try {
          return convertFromString(localStorageValue)
        } catch {
          localStorage.removeItem(key)
        }
        // change ends here
      }
      return typeof defaultValue === 'function' ? defaultValue() : defaultValue
    }
    
    우리 모든 것을 함께 놓자.
    function getInitialValue(key, defaultValue, convertFromString) {
      const localStorageValue = localStorage.getItem(key);
      if(localStorageValue) {
        try {
          return convertFromString(localStorageValue)
        } catch {
          localStorage.removeItem(key)
        }
      }
      return typeof defaultValue === 'function' ? defaultValue() : defaultValue
    }
    
    function useLocalStorageState(
      key,
      defaultValue = "",
      { convertToString = JSON.stringify, convertFromString = JSON.parse } = {}
    ) {
      const [state, setState] = useState(() =>
        getInitialValue(key, defaultValue, convertFromString)
      );
    
      useEffect(() => {
        localStorage.setItem(key, convertToString(state));
      }, [key, state, convertToString]);
    
      return [state, setState];
    }
    
    그렇습니다.로컬 저장소에 상태를 저장하고 실제 상태와 동기화하려면 이 갈고리를 사용할 수 있습니다.API도 사용자 방식과 유사합니다convertFromString.
    const [state, setState] = useLocalStorageState('state', {})
    

    뭐 공부 해요?

  • Useffect 연결
  • 구성 요소가 렌더링될 때마다 실행되고 의존 항목이 전달되지 않을 때 다시 렌더링됩니다.
  • 는 의존 관계 수조를 두 번째 매개 변수로 전달할 수 있다.
  • useState
  • 리셋은 의존 항목의 값이 변경되었을 때만 실행됩니다.
  • 빈 그룹을 의존 그룹으로 전달하면 리셋은 구성 요소가 처음 나타난 후에만 실행됩니다.
  • useEffect 재사용 가능한 로컬 저장소 연결을 만드는 방법도 배웠습니다.
  • 다음은 뭐예요?


    다음 문장에서 우리는 연결된 절차를 보게 될 것이다.우리는 구성 요소의 생명 주기에서 서로 다른 갈고리가 언제 운행되는지, 특히 useStateuseEffect 를 정확하게 볼 수 있을 것이다.

    다음까지👋


    참고 문헌:


  • EpicReact.DevbyKent C. Dodds
  • React Hooks Workshop Prod Deployment
  • React Hooks Workshop Repo
  • 당신이 좋아할 수 있는 기타 물품:
  • React Hooks: Managing State With useState Hook
  • React Fundamentals: Styling And Handling Forms
  • React Fundamentals: Creating Custom Components
  • React Fundamentals: Understanding JSX
  • React Fundamentals: Intro to React Raw APIs
  • Javascript You Need To Know For React
  • My Review of Kent C. Dodds's EpicReact.Dev: Introduction
  • 만약 이것이 당신에게 도움이 된다면, 다른 사람에게도 전해질 수 있도록 좋아하고 나누세요.나의 최신 글에 대한 이메일 알림을 받으려면 페이지 맨 위에 있는 구독 단추 구독 my blog 을 누르십시오.너도 트위터에서 나를 팔로우할 수 있다.

    좋은 웹페이지 즐겨찾기