introduces useLocalStorage hook

This commit is contained in:
Mose Müller 2024-07-22 07:04:32 +02:00
parent 1789a6ad7e
commit 9e0adba8dc
3 changed files with 29 additions and 26 deletions

View File

@ -12,6 +12,7 @@ import { setNestedValueByPath, State } from "./utils/stateUtils";
import { WebSettingsContext, WebSetting } from "./WebSettings"; import { WebSettingsContext, WebSetting } from "./WebSettings";
import { GenericComponent } from "./components/GenericComponent"; import { GenericComponent } from "./components/GenericComponent";
import { SerializedObject } from "./types/SerializedObject"; import { SerializedObject } from "./types/SerializedObject";
import useLocalStorage from "./hooks/useLocalStorage";
type Action = type Action =
| { type: "SET_DATA"; data: State } | { type: "SET_DATA"; data: State }
@ -53,15 +54,15 @@ const App = () => {
const [state, dispatch] = useReducer(reducer, null); const [state, dispatch] = useReducer(reducer, null);
const [serviceName, setServiceName] = useState<string | null>(null); const [serviceName, setServiceName] = useState<string | null>(null);
const [webSettings, setWebSettings] = useState<Record<string, WebSetting>>({}); const [webSettings, setWebSettings] = useState<Record<string, WebSetting>>({});
const [isInstantUpdate, setIsInstantUpdate] = useState(() => { const [isInstantUpdate, setIsInstantUpdate] = useLocalStorage(
const saved = localStorage.getItem("isInstantUpdate"); "isInstantUpdate",
return saved !== null ? JSON.parse(saved) : false; false,
}); );
const [showSettings, setShowSettings] = useState(false); const [showSettings, setShowSettings] = useState(false);
const [showNotification, setShowNotification] = useState(() => { const [showNotification, setShowNotification] = useLocalStorage(
const saved = localStorage.getItem("showNotification"); "showNotification",
return saved !== null ? JSON.parse(saved) : false; false,
}); );
const [notifications, setNotifications] = useState<Notification[]>([]); const [notifications, setNotifications] = useState<Notification[]>([]);
const [connectionStatus, setConnectionStatus] = useState("connecting"); const [connectionStatus, setConnectionStatus] = useState("connecting");
@ -115,14 +116,6 @@ const App = () => {
}; };
}, []); }, []);
// Persist isInstantUpdate and showNotification state changes to localStorage
useEffect(() => {
localStorage.setItem("isInstantUpdate", JSON.stringify(isInstantUpdate));
}, [isInstantUpdate]);
useEffect(() => {
localStorage.setItem("showNotification", JSON.stringify(showNotification));
}, [showNotification]);
// Adding useCallback to prevent notify to change causing a re-render of all // Adding useCallback to prevent notify to change causing a re-render of all
// components // components
const addNotification = useCallback( const addNotification = useCallback(

View File

@ -1,10 +1,10 @@
import { useEffect, useState } from "react";
import React from "react"; import React from "react";
import { Card, Collapse } from "react-bootstrap"; import { Card, Collapse } from "react-bootstrap";
import { ChevronDown, ChevronRight } from "react-bootstrap-icons"; import { ChevronDown, ChevronRight } from "react-bootstrap-icons";
import { GenericComponent } from "./GenericComponent"; import { GenericComponent } from "./GenericComponent";
import { LevelName } from "./NotificationsComponent"; import { LevelName } from "./NotificationsComponent";
import { SerializedObject } from "../types/SerializedObject"; import { SerializedObject } from "../types/SerializedObject";
import useLocalStorage from "../hooks/useLocalStorage";
interface DataServiceProps { interface DataServiceProps {
props: DataServiceJSON; props: DataServiceJSON;
@ -19,15 +19,7 @@ export type DataServiceJSON = Record<string, SerializedObject>;
export const DataServiceComponent = React.memo( export const DataServiceComponent = React.memo(
({ props, isInstantUpdate, addNotification, displayName, id }: DataServiceProps) => { ({ props, isInstantUpdate, addNotification, displayName, id }: DataServiceProps) => {
// Retrieve the initial state from localStorage, default to true if not found // Retrieve the initial state from localStorage, default to true if not found
const [open, setOpen] = useState(() => { const [open, setOpen] = useLocalStorage(`dataServiceComponent-${id}-open`, true);
const savedState = localStorage.getItem(`dataServiceComponent-${id}-open`);
return savedState !== null ? JSON.parse(savedState) : true;
});
// Update localStorage whenever the state changes
useEffect(() => {
localStorage.setItem(`dataServiceComponent-${id}-open`, JSON.stringify(open));
}, [open]);
if (displayName !== "") { if (displayName !== "") {
return ( return (

View File

@ -0,0 +1,18 @@
import { useState, useEffect } from "react";
export default function useLocalStorage(key: string, defaultValue: unknown) {
const [value, setValue] = useState(() => {
const storedValue = localStorage.getItem(key);
if (storedValue) {
return JSON.parse(storedValue);
}
return defaultValue;
});
useEffect(() => {
if (value === undefined) return;
localStorage.setItem(key, JSON.stringify(value));
}, [value, key]);
return [value, setValue];
}