Skip to content

Commit

Permalink
fix: updated main.ts, useStorage.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
AssahBismarkabah committed Mar 18, 2024
1 parent c6a61e1 commit e5aff4c
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 84 deletions.
117 changes: 56 additions & 61 deletions power-pay-frontend/src/hooks/StorageContext.tsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,86 @@
import { createContext, PropsWithChildren, useEffect } from 'react';
import { useStorage } from './useStorage';



// Creating a fake implementation of the StorageContextData interface.
const fakeStorage: StorageContextData<unknown> = {
getItem: async (key: string): Promise< unknown | undefined> => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item): undefined;
},
setItem: async (key: string, value: unknown): Promise<boolean> => {
localStorage.setItem(key, JSON.stringify(value));
return true;
},
removeItem: async (key: string): Promise<boolean> => {
localStorage.removeItem(key);
return true;
},
clear: async (): Promise<boolean> => {
localStorage.clear();
return true;
},
};
import { createContext, PropsWithChildren, useEffect, useState } from 'react';


// Create the StorageContextData interface.
interface StorageContextData<T> {
getItem: (key: string) => Promise<unknown | undefined>;
setItem: (key: string, value: T) => Promise<boolean>;
removeItem: (key: string) => Promise<boolean>;
clear: () => Promise<boolean>;
item: Record<string, T>;
setItem: (key: string, value: T) => Promise<boolean>; // adding a key into the map
removeItem: (key: string) => Promise<boolean>; // remove a key from the map
clear: () => Promise<boolean>; // clear the map
}

interface StorageService<T> {
getItem: (key: string) => Promise<T | undefined>;
setItem: (key: string, value: T) => Promise<boolean>;

interface StorageService {
getItem: <T>(key: string) => Promise<T | undefined>;
setItem: <T>(key: string, value: T) => Promise<boolean>;
removeItem: (key: string) => Promise<boolean>;
clear: () => Promise<boolean>;
}


export class LocalStorageService implements StorageService {
removeItem!: (key: string) => Promise<boolean>;
clear!: () => Promise<boolean>;
async getItem<T>(key: string) {
const found = localStorage.getItem(key);
if (!found) return undefined;
return JSON.parse(found) as T;
}

async setItem<T>(key: string, value: T) {
localStorage.setItem(key, JSON.stringify(value));
return true;
}

}


// Define a global constant for the key.
const STORAGE_KEY = 'key';

// Create the StorageContext with default functions for getItem and setItem.
const StorageContext = createContext<StorageService<unknown> | undefined>(undefined);
const StorageContext = createContext<StorageContextData<unknown> | undefined>(undefined);

// StorageProvider: A React component that wraps the application and provides the storage context with getItem and setItem methods.
export function StorageProvider<T>({ initialValue, children }: PropsWithChildren<{ initialValue?: T }>) {
const [storedValue, setStoredValue] = useStorage<T | undefined>({ key: 'your_key_here', initialValue });

// Define a global constant for the key.
const STORAGE_KEY = 'key';
export function StorageProvider<T>({ children, storageService }: PropsWithChildren<{ storageService: StorageService }>) {
const [storedValue, setStoredValue] = useState<Record<string, unknown>>({});

// Initializes the state with the value from the local storage if it exists.
useEffect(() => {
const item = localStorage.getItem(STORAGE_KEY);
if (item) {
setStoredValue(JSON.parse(item));
}
}, [setStoredValue]);
storageService
.getItem<Record<string, T>>(STORAGE_KEY)
.then((item) => {
if (item) {
setStoredValue(item);
}
});
}, [storageService]);

// Updates the local storage whenever the state changes.
useEffect(() => {
if (storedValue !== undefined) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(storedValue));
}
}, [storedValue]);

// Defining a wrapper function for the setItem method that updates the local storage and the state with the new value.
const setItemWrapper = async (key: string, value: T | undefined) => {
if (value !== undefined) {
localStorage.setItem(key, JSON.stringify(value));
} else {
localStorage.removeItem(key);
storageService.setItem(STORAGE_KEY, storedValue);
}
setStoredValue(value);
return true;
};
}, [storageService, storedValue]);

// Destructure getItem and setItem before using them in the StorageContext.Provider value prop.
const contextValue: StorageService<T> = {
getItem: (key) => fakeStorage.getItem(key),
setItem: (key, value) => setItemWrapper(key, value),
removeItem: (key) => fakeStorage.removeItem(key),
clear: () => fakeStorage.clear(),
const contextValue: StorageContextData<unknown> = {
item: storedValue,
setItem: async (key, value) => {
setStoredValue(pre => ({
...pre, [key]: value
}))
return true;
},


removeItem: (key) => storageService.removeItem(key),

clear: () => storageService.clear(),
};

return (
<StorageContext.Provider value={contextValue as StorageService<unknown>}>
<StorageContext.Provider value={contextValue}>
{children}
</StorageContext.Provider>
);
Expand Down
44 changes: 23 additions & 21 deletions power-pay-frontend/src/hooks/useStorage.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { useState } from 'react';

// UseStorageProps<T>: An interface defining the props for the useStorage hook
import { useContext, useEffect, useState } from 'react';
import StorageContext, { StorageContextData } from './StorageContext';

interface UseStorageProps<T> {
key: string; // the key to use for storing and retrieving the value from local storage
initialValue?: T | undefined; // the initial value to use for the state variable
key: string;
initialValue?: T | undefined;
}

// useStorage<T = string>: A generic function that accepts a UseStorageProps<T> object.
export function useStorage<T = string>(props: UseStorageProps<T>): [T, React.Dispatch<React.SetStateAction<T>>, () => void] {
const { key, initialValue } = props;

// storedValue: A state variable that stores the value retrieved from the localStorage using the provided key
const [storedValue, setStoredValue] = useState<T>(() => {
// Retrieve the value from local storage using the provided key
const valueInLocalStorage = localStorage.getItem(key);
export function useStorage<T = string>({ key, initialValue }: UseStorageProps<T>): [T, React.Dispatch<React.SetStateAction<T>>, () => void] {
const { item, setItem, removeItem } = useContext(StorageContext) as StorageContextData<T>;

// If the value exists, parse it from JSON and return it. Otherwise, return the initial value.
return valueInLocalStorage ? JSON.parse(valueInLocalStorage) : initialValue!;
// Initialize the state variable with the initial value or the value from the local storage
const [storedValue, setStoredValue] = useState<T | undefined>(() => {
return item[key] ?? initialValue;
});

// adding a new function removeValue to remove the stored value from the localstorage and set it to its initial state
const removeValue = () => {
// Set the storedValue to the initial value
setStoredValue(initialValue!);
// Another useEffect for updating the stored value when the context changes
useEffect(() => {
setStoredValue(item[key] ?? initialValue);
}, [item, key, initialValue]);

useEffect(() => {
setItem(key, storedValue!);
}, [key, storedValue, setItem]);

// Remove the value from local storage using the provided key
localStorage.removeItem(key);
// Remove the item from local storage and set the stored value to undefined
const clearItem = () => {
removeItem(key);
setStoredValue(undefined)
};

// Return the storedValue, setStoredValue function, and removeValue function as an array
return [storedValue, setStoredValue, removeValue];
return [storedValue!, setItem, clearItem];
}
6 changes: 4 additions & 2 deletions power-pay-frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import { StorageProvider } from './hooks/StorageContext';
import { LocalStorageService, StorageProvider } from './hooks/StorageContext';
import App from './App.tsx'
import './index.css'

const storageService = new LocalStorageService();

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<StorageProvider>
<StorageProvider storageService={storageService}>
<App />
</StorageProvider>
</React.StrictMode>,
Expand Down

0 comments on commit e5aff4c

Please sign in to comment.