useMap
Introduction
useMap
훅은 React 애플리케이션에서 키-값 쌍의 맵 상태를 효과적으로 관리하기 위한 커스텀 훅입니다. 이 훅을 사용하면 맵 상태를 손쉽게 생성하고 조작할 수 있습니다.
기능:
맵 상태 초기화: 초기 상태를 설정할 수 있으며, 빈 맵이나 키-값 쌍의 배열로 초기화할 수 있습니다.
세터 액션 제공:
set
을 사용하여 새로운 키-값 쌍을 추가하거나 기존 키의 값을 갱신할 수 있습니다.일괄 설정 액션:
setAll
을 사용하여 주어진 맵이나 키-값 쌍의 배열로 맵 상태를 한 번에 설정할 수 있습니다.키 제거 액션:
remove
를 사용하여 주어진 키에 해당하는 항목을 맵에서 제거할 수 있습니다.맵 초기화 액션:
reset
을 사용하여 맵 상태를 초기화하여 빈 맵으로 만들 수 있습니다.
Example
import React from "react";
// useMap 훅을 사용한 컴포넌트 정의
const MapComponent: React.FC = () => {
// useMap 훅을 사용하여 맵 상태와 액션을 초기화
const [map, mapActions] = useMap<string, number>([
['하나', 1],
['둘', 2],
['셋', 3],
]);
// 새로운 키-값 쌍을 추가하는 함수
const handleSet = () => {
mapActions.set('넷', 4);
};
// 맵에서 특정 키를 제거하는 함수
const handleRemove = () => {
mapActions.remove('둘');
};
// 맵을 초기화하는 함수
const handleReset = () => {
mapActions.reset();
};
return (
<div>
<h2>맵 컴포넌트</h2>
<p>현재 맵 상태: {JSON.stringify([...map])}</p>
<button onClick={handleSet}>'넷': 4 추가</button>
<button onClick={handleRemove}'둘' 제거</button>
<button onClick={handleReset}>맵 초기화</button>
</div>
);
};
export default MapComponent;
useMap
훅을 사용하여map
상태와mapActions
액션을 초기화합니다.컴포넌트는 현재 맵 상태를 렌더링합니다.
set
,remove
,reset
액션의 사용법을 보여주기 위한 버튼이 있습니다.handleSet
,handleRemove
,handleReset
함수는 각각 해당 액션을 사용하여 맵 상태를 수정합니다
Hook
import type { Dispatch, SetStateAction } from "react";
import { useCallback, useEffect, useState } from "react";
type SetValue<T> = Dispatch<SetStateAction<T>>;
interface Options {
initialSave: boolean;
}
const isServer = typeof window === "undefined";
/**
* 이 훅은 로컬스토리지를 관리하는 커스텀 훅 입니다.
* 기본적으로 로컬스토리지의 값을 읽기, 저장, 삭제, 업데이트 등의 기능을 제공하고 있습니다.
* @param {string} key - 로컬 스토리지의 Key
* @param {T} initialValue - 로컬 스토리지의 초깃값
* @param {Options} options - 훅에서 쓰이는 옵션 값
* @returns {()=>{}} read(읽기), save(저장), remove(삭제), update(업데이트 마운트)
*/
/**
*
* @param options
* @description options의 기능에 대한 설명
* initialSave : 스토리지에 저장된 값이 없을 경우, 초기값을 저장할 것인지 말 것인지 type : boolean
*/
export default function useLocalStorage<T>(key: string, initialValue: T | (() => T), options: Options = { initialSave: false }) {
const [storedValue, setStoredValue] = useState<T>(initialValue);
const isStorageEvent = (event: StorageEvent | CustomEvent): event is StorageEvent => {
return "key" in event;
};
/** 로컬 스토리지 읽기 */
const readValueFromLocalStorage = (): T => {
const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue;
// SSR에서 발생할 수 있는 오류 방지하기 위해 설정. window 객체가 존재하지 않을때, localStorage에 접근 하는 것을 방지
if (isServer) {
return initialValueToUse;
}
try {
const rawData = window.localStorage.getItem(key) as T;
/** 값이 없을 경우 */
if (typeof rawData === "object" && rawData === null && options.initialSave) {
save(initialValueToUse);
return initialValueToUse;
}
return rawData ? rawData : initialValueToUse;
} catch {
console.warn(`로컬 스토리지를 가져오는 것에 실패하였습니다. 키 : "${key}", 값 : error `);
return initialValueToUse;
}
};
// read함수 메모이제이션
const read = useCallback<() => T>(() => {
return readValueFromLocalStorage();
}, []);
useEffect(() => {
setStoredValue(read());
}, [key]);
/** 로컬 스토리지 읽기 */
/** 로컬 스토리지 저장 */
const saveValueFromLocalStorage = (value: T) => {
if (isServer) {
console.warn("브라우저 환경에서만 사용 가능합니다. 서버환경에서 사용이 불가능합니다.");
return undefined;
}
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
return value;
} catch (error) {
if (error instanceof DOMException && error.name === "QuotaExceededError") {
console.error("실패 : 로컬 스토리지 용량이 부족합니다.");
} else {
console.warn(`로컬 스토리지에 값을 저장하는 데 실패했습니다. 키: "${key}"`);
}
}
};
const save: SetValue<T> = useCallback(async (value: T) => {
return await saveValueFromLocalStorage(value);
}, []);
/** 로컬 스토리지 저장 */
/** 로컬 스토리지 변화에 따른 상태관리 감지 */
const update = useCallback(
(event: StorageEvent | CustomEvent) => {
if (isStorageEvent(event) && event.key !== key) return;
setStoredValue(read());
},
[key, read]
);
/** 로컬 스토리지 변화에 따른 상태관리 감지 */
/** 로컬 스토리지 삭제 */
const remove = () => {
if (isServer) {
console.warn("현재 브라우저 환경이 아닙니다.");
return key;
}
try {
window.localStorage.removeItem(key);
setStoredValue(undefined);
} catch (error) {
console.warn(`로컬 스토리지에서 항목을 삭제하는 데 실패했습니다. 키: "${key}"`);
return;
}
};
return { read, save, remove, update };
}
Last updated