사용자 지정 반응 연결:useLocalStorage

이 시리즈의 마지막 부분에서 우리는 갈고리를 실현하여 진열 관리를 간소화하였다.오늘 방송에서는 로컬 스토리지 관리를 단순화하는 훅을 만듭니다useLocalStorage.
  • Motivation
  • Implementation
  • Usage
  • Improvement Ideas
  • Conclusion
  • 모티프


    우선 이 갈고리를 왜 실현해야 하는지 살펴보자.모든 사용자에게 테마, 언어, 설정... 을 사용하는 프로그램을 만들고 있다고 가정하십시오.구성을 저장하려면 다음과 같은 객체를 사용합니다.
    const config = {
        theme: 'dark',
        lang: 'fr',
        settings: {
            pushNotifications: true
        }
    }
    
    이제 루트 구성 요소 또는 설정 페이지에서 사용자 정의 설정을 사용할 수 있습니다. 이 경우 UI 상태를 로컬 스토리지와 동기화해야 합니다.예를 들어, 설정 페이지는 다음과 같습니다.

    해당 소스 코드는 이와 유사할 수 있습니다.
    const defaultConfig = {
        theme: 'dark',
        lang: 'fr',
        settings: {
            pushNotifications: true
        }
    };
    
    const Settings = () => {
        const [config, setConfig] = useState(() => {
            const saved = localStorage.getItem('config');
            if (saved !== null) {
                return JSON.parse(saved);
            }
            return defaultConfig;
        });
    
        const handleChange = (e) => {
            setConfig(oldConfig => {
                const newConfig = {
                    ...oldConfig,
                    settings: {
                        ...oldConfig.settings,
                        pushNotifications: e.target.checked
                    }
                };
    
                localStorage.setItem('config', JSON.stringify(newConfig));
                return newConfig;
            })
        }
    
        return (
            <>
                <h1>Settings</h1>
                <label htmlFor="pushNotifications">
                    Push Notifications
                </label>
                <input
                    type="checkbox"
                    id="pushNotifications"
                    checked={config.settings.pushNotifications}
                    onChange={handleChange}
                />
            </>
        );
    };
    
    보시다시피...전송 알림 설정만 바꾸면 이미 많은 코드가 있습니다!또한 구성 상태를 로컬 스토리지와 수동으로 동기화해야 하므로 매우 번거롭습니다.만약 우리가 충분한 중시를 하지 않는다면, 이것은 약간의 동기화를 초래할 수 있다.
    우리의 userLocalStorage 갈고리를 통해 우리는 이러한 간단한 기능에 필요한 코드량을 줄이기 위해 하나의 단독 함수에서 통용 논리를 추상화할 수 있다.그 밖에 우리는 더 이상 어떤 것도 동기화할 필요가 없을 것이다. 왜냐하면 이것은 갈고리의 일이 될 것이다.

    구현


    우선 갈고리의 서명 (즉, 갈고리의 매개 변수와 되돌아오는 값이 무엇인지) 에 대해 토론합시다.로컬 저장소는 일부 문자열 값을 키에 연결해서 작동합니다.
    // Get the value associated with the 'config' key
    const rawConfig = localStorage.getItem('config');
    
    // Parse the plain object corresponding to the string
    const config = JSON.parse(rawConfig);
    
    // Save the config
    localStorage.setItem('config', JSON.stringify(config));
    
    그래서 우리의 갈고리 사인은 이렇게 할 수 있다.
    const [config, setConfig] = useLocalStorage('config');
    
    갈고리는 config 변수를 "config" 키의 로컬 저장소에서 찾을 수 있는 값으로 설정합니다.그런데 얘가 아무것도 못 찾으면?이 경우 config 변수는 null로 설정됩니다.이 변수의 로컬 저장이 비어 있지 않도록 기본값을 설정하기를 원합니다.이를 위해, 새로운 선택할 수 있는 인자: 기본값을 받아들이기 위해 갈고리의 서명을 약간 변경할 것입니다.
    const [config, setConfig] = useLocalStorage('config', defaultConfig);
    
    우리는 지금 갈고리를 실현하기 시작할 준비가 되어 있다.우선, 우리는 key 매개 변수에 대응하는 로컬 저장 값을 읽을 것이다.존재하지 않으면 기본값을 되돌려줍니다.
    const useLocalStorage = (key, defaultValue = null) => {
        const [value, setValue] = useState(() => {
            const saved = localStorage.getItem(key);
            if (saved !== null) {
                return JSON.parse(saved);
            }
            return defaultValue;
        });
    };
    
    위대하다우리는 이미 실시의 첫걸음을 내디뎠다.지금 JSON.parse 방법이 오류를 던지면 무슨 일이 일어날까요?우리는 아직 이 사건을 처리하지 못했다.기본값을 다시 되돌려서 이 문제를 해결합시다.
    const useLocalStorage = (key, defaultValue = null) => {
        const [value, setValue] = useState(() => {
            try {
                const saved = localStorage.getItem(key);
                if (saved !== null) {
                    return JSON.parse(saved);
                }
                return defaultValue;
            } catch {
                return defaultValue;
            }
        });
    };
    
    이게 더 좋아요!다음은요?우리는 변경 사항을 감청하고 로컬 저장소를 업데이트하기만 하면 된다.우리는 value 갈고리를 사용하여 이 조작을 실행할 것이다.
    const useLocalStorage = (key, defaultValue = null) => {
        const [value, setValue] = useState(...);
    
        useEffect(() => {
            const rawValue = JSON.stringify(value);
            localStorage.setItem(key, rawValue);
        }, [value]);
    };
    

    ⚠️ Be aware that the JSON.stringify method can also throw errors. However, this time, it is not the job of this hook to handle those errors — except if you want to catch them in order to throw a custom one.


    그럼, 우리 끝났어요?아직.우선, 우리는 어떤 것도 돌려주지 않았다.갈고리의 서명에 따라, 우리는 값과setter를 되돌려주기만 하면 된다.
    const useLocalStorage = (key, defaultValue = null) => {
        const [value, setValue] = useState(...);
    
        useEffect(...);
    
        return [value, setValue];
    };
    
    하지만 우리도 useEffect의 변화에 귀를 기울여야 한다!실제로, 우리의 예시에서 매개 변수로 제공된 값은 상수 ((key 이지만, 항상 그렇지는 않을 수도 있습니다. 이것은 'config' 호출로 만들어진 값일 수도 있습니다.우리도 이 문제를 해결하자.
    const useLocalStorage = (key, defaultValue = null) => {
        const [value, setValue] = useState(...);
    
        useEffect(() => {
            const rawValue = JSON.stringify(value);
            localStorage.setItem(key, rawValue);
        }, [key, value]);
    
        return [value, setValue];
    };
    
    저희 이제 끝났나요?응, 그래...아니, 왜 안 해?왜냐하면 너는 자신의 방식에 따라 이 갈고리를 맞춤 제작할 수 있기 때문이다!예를 들어 세션 저장소를 처리해야 한다면 useState 호출을 localStorage 호출로 변경하면 된다.주어진 키와 관련된 로컬 저장 값을 제거하기 위해 sessionStorage 함수를 추가하는 등 다른 장면도 상상할 수 있다.요컨대 가능성은 무궁무진하다. 나는 다음 절에서 당신에게 증강된 아이디어를 제공할 것이다.

    사용법


    설정 페이지의 예로 돌아가십시오.이제 우리는 새로운 갈고리 간소화 코드를 사용할 수 있다.그것 덕분에 우리는 더 이상 어떤 것도 동기화할 필요가 없다.다음은 코드의 현재 모습입니다.
    const defaultConfig = {
      theme: "light",
      lang: "fr",
      settings: {
        pushNotifications: true
      }
    };
    
    const Settings = () => {
      const [config, setConfig] = useLocalStorage("config", defaultConfig);
    
      const handleChange = (e) => {
        // Still a bit tricky, but we don't really have any other choice
        setConfig(oldConfig => ({
          ...oldConfig,
          settings: {
            ...oldConfig.settings,
            pushNotifications: e.target.checked
          }
        }));
      };
    
      return (
        <>
          <h1>Settings</h1>
    
          <label htmlFor="pushNotifications">Push Notifications</label>
          <input
            type="checkbox"
            id="pushNotifications"
            checked={config.settings.pushNotifications}
            onChange={handleChange}
          />
        </>
      );
    };
    

    생각을 개선하다.

  • 처리해야 할 경우clear 방법의 이상
  • 값이 JSON.stringify로 변경되면 로컬 스토리지 키 지우기(사용null
  • 키가 변경되면 기존 키와 관련된 값을 삭제하여 불필요한 스토리지 공간 사용을 방지하십시오
  • .

    결론


    나는 이 갈고리가 너의 프로젝트에 유용하길 바란다.질문이 있으시면 언제든지 논평 부분에서 질문해 주십시오.
    제 글을 읽어 주셔서 감사합니다. 다음에 저희는 귀하께 새로운 맞춤형 연결을 제공할 것입니다.🤗
    소스 코드는 CodeSandbox에서 얻을 수 있습니다.

    나를 지지하다


    만약 당신이 나를 지지하고 싶다면, 당신은 아래의 링크로 나에게 커피 한 잔을 사줄 수 있다. (그리고 나는 커피를 새로운 맞춤형 연결고리로 바꿀 수도 있다.)☕)

    좋은 웹페이지 즐겨찾기