Code snippets for Custom Hooks that mostly used in my projects
1
2import { useState, useEffect } from 'react';
3
4function useLocalStorage(key, initialValue) {
5 const isClient = typeof window === 'object';
6
7 const [storedValue, setStoredValue] = useState(() => {
8 if (!isClient) return initialValue;
9 try {
10 const item = window.localStorage.getItem(key);
11 return item ? JSON.parse(item) : initialValue;
12 } catch (error) {
13 console.warn(`Error reading localStorage key "${key}":`, error);
14 return initialValue;
15 }
16 });
17
18 useEffect(() => {
19 if (!isClient) return;
20 try {
21 window.localStorage.setItem(key, JSON.stringify(storedValue));
22 } catch (error) {
23 console.warn(`Error setting localStorage key "${key}":`, error);
24 }
25 }, [key, storedValue, isClient]);
26
27 return [storedValue, setStoredValue];
28}
29
30export default useLocalStorage;
31
Please provide your own decodeBase64Unicode, encodeBase64Unicode
1import { decodeBase64Unicode, encodeBase64Unicode } from "@/lib/utils";
2import { useState, useEffect } from "react";
3
4/**
5 * A custom hook that syncs a state value to localStorage,
6 * **Base64-encoding** the JSON string in a Unicode-safe manner.
7 *
8 * @param key The key to store in localStorage
9 * @param initialValue The default value if none is in localStorage
10 * @returns [value, setValue]
11 */
12export function useEncodeLocalStorage<T>(
13 key: string,
14 initialValue: T
15): [T, React.Dispatch<React.SetStateAction<T>>] {
16 const [storedValue, setStoredValue] = useState<T>(() => {
17 try {
18 const item = localStorage.getItem(key);
19 if (item) {
20 // Decode base64 safely and parse JSON
21 const decoded = decodeBase64Unicode(item);
22 return JSON.parse(decoded) as T;
23 }
24 } catch (error) {
25 console.error(
26 "useEncodeLocalStorage: Error loading from localStorage",
27 error
28 );
29 }
30 return initialValue;
31 });
32
33 useEffect(() => {
34 try {
35 const json = JSON.stringify(storedValue);
36 const encoded = encodeBase64Unicode(json);
37 localStorage.setItem(key, encoded);
38 } catch (error) {
39 console.error(
40 "useEncodeLocalStorage: Error saving to localStorage",
41 error
42 );
43 }
44 }, [key, storedValue]);
45
46 return [storedValue, setStoredValue];
47}
48
1
2import { FetchError } from "./../data/types";
3import { useState, useCallback } from "react";
4
5interface FetchOptions extends RequestInit {
6 body?: any;
7}
8
9export interface UseFetchReturn<T> {
10 data: T | null;
11 setData: React.Dispatch<React.SetStateAction<T | null>>;
12 loading: boolean;
13 error: FetchError | null;
14 setError: React.Dispatch<React.SetStateAction<FetchError | null>>;
15 execute: (options?: FetchOptions) => Promise<void>;
16}
17
18const useFetch = <T = unknown>(
19 initialUrl: string,
20 initialOptions: FetchOptions = {}
21): UseFetchReturn<T> => {
22 const [url, setUrl] = useState<string>(initialUrl);
23 const [options, setOptions] = useState<FetchOptions>(initialOptions);
24 const [data, setData] = useState<T | null>(null);
25 const [loading, setLoading] = useState<boolean>(false);
26 const [error, setError] = useState<FetchError | null>(null);
27
28 const execute = useCallback(
29 async (overrideOptions?: FetchOptions) => {
30 setLoading(true);
31 setError(null);
32 try {
33 const response = await fetch(url, {
34 ...options,
35 ...overrideOptions
36 });
37
38 if (!response.ok) {
39 const errorText = await response.text();
40 throw new Error(
41 JSON.stringify(
42 {
43 status: response.status,
44 name: response.statusText,
45 message: errorText
46 },
47 null,
48 2
49 )
50 );
51 }
52
53 const responseData: T = await response.json();
54 setData(responseData);
55 } catch (err) {
56 const errJson = JSON.parse(err?.message || "{}");
57 console.log(errJson);
58 setError({
59 status: errJson?.status || 500,
60 name: errJson?.name || "Error",
61 message: `${errJson?.message || "Unknown error"}`
62 });
63 } finally {
64 setLoading(false);
65 }
66 },
67 [url, options]
68 );
69
70 return { data, setData, loading, error, setError, execute };
71};
72
73export default useFetch;
74