Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: useStorage hook to persist data on frontend #83

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1920a34
feat: added useStorage hook to persist data on frontend
AssahBismarkabah Mar 7, 2024
7e7ea0f
fix: reimplement useStorage hook in typescrpt
AssahBismarkabah Mar 8, 2024
370d3bb
#deleted: power-pay-frontend/src/components/useStorage.js
AssahBismarkabah Mar 8, 2024
af59378
feat: Add global context for interacting with localStorage and fix im…
AssahBismarkabah Mar 8, 2024
f1738d5
fix: Add global context for interacting with localStorage and fix imp…
AssahBismarkabah Mar 11, 2024
7b7f933
fix: updated storagecontext
AssahBismarkabah Mar 11, 2024
c04d849
fix: updated storagecontext
AssahBismarkabah Mar 11, 2024
c8c5c73
fix: updated storagecontext
AssahBismarkabah Mar 11, 2024
de3dd35
fix: updated storagecontext
AssahBismarkabah Mar 11, 2024
6ae1246
fix: updated login component
AssahBismarkabah Mar 11, 2024
6e02da0
fix: storagecontext
AssahBismarkabah Mar 11, 2024
1a1782d
fix: modified storageContext
AssahBismarkabah Mar 11, 2024
0e9a795
fix: updated package.json with the corresponding dependecies
AssahBismarkabah Mar 11, 2024
44e30a8
Merge branch 'main' into feature/use-storage-hook
AssahBismarkabah Mar 11, 2024
4f189c2
fix: use a type assertion to ensure compatibility between setItem in …
AssahBismarkabah Mar 11, 2024
2faa9bb
fix: updated storageContext.tsx
AssahBismarkabah Mar 11, 2024
7974f91
updated main.tsx
AssahBismarkabah Mar 12, 2024
48933b5
fix: updated removeValue
AssahBismarkabah Mar 12, 2024
6cc7740
fix: updated usestorage.ts -> hook does not interact with the storage
AssahBismarkabah Mar 12, 2024
562946a
fix: removed duplicate usestorage hook
AssahBismarkabah Mar 12, 2024
4ab0b57
fix: updated storagecontext.tsx
AssahBismarkabah Mar 13, 2024
e1d7d33
fix: added fakeimpl
AssahBismarkabah Mar 13, 2024
f700b50
fix: updated storagecontext.tsx
AssahBismarkabah Mar 13, 2024
d3d1db1
fix: updated main.tsx
AssahBismarkabah Mar 17, 2024
2f66278
fix: updated usestorage
AssahBismarkabah Mar 17, 2024
c6a61e1
fix: updated storagecontext
AssahBismarkabah Mar 17, 2024
e5aff4c
fix: updated main.ts, useStorage.ts
AssahBismarkabah Mar 18, 2024
695395a
fix: updated the logic in the usestorage.ts
AssahBismarkabah Mar 19, 2024
4cac1c5
fix: complete implementation of localstorageservice
AssahBismarkabah Mar 19, 2024
1ccb620
Merge branch 'main' into feature/use-storage-hook
AssahBismarkabah Mar 19, 2024
9c1ec67
fix: updated package.json to previous version
AssahBismarkabah Mar 19, 2024
089b27e
fix: removed updated storagecontext.tsx Removed the unnecessary line …
AssahBismarkabah Mar 20, 2024
e933383
fix: remove if condition before calling storageService.setItem
AssahBismarkabah Mar 20, 2024
cc5f16f
fix: updated useStorage.ts
AssahBismarkabah Mar 20, 2024
f0311de
fix: updated storagecontext.tsx
AssahBismarkabah Mar 20, 2024
2424a9e
fix: updated storagecontext.tsx
AssahBismarkabah Mar 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions power-pay-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions power-pay-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.56",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.19",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
Expand All @@ -27,8 +27,12 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"gh-pages": "^6.1.1",

"typescript": "^5.4.2",

"sass": "^1.71.1",
"typescript": "^5.2.2",


"vite": "^5.1.4"
}
}
89 changes: 89 additions & 0 deletions power-pay-frontend/src/hooks/StorageContext.tsx
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { createContext, PropsWithChildren, useEffect, useState } from 'react';


// Create the StorageContextData interface.
interface StorageContextData<T> {
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
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 {
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
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>;
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
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<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>({ 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(() => {
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) {
storageService.setItem(STORAGE_KEY, storedValue);
}
}, [storageService, storedValue]);

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


removeItem: (key) => storageService.removeItem(key),
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved

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

return (
<StorageContext.Provider value={contextValue}>
{children}
</StorageContext.Provider>
);
}

export default StorageContext;
35 changes: 35 additions & 0 deletions power-pay-frontend/src/hooks/useStorage.ts
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

import { useContext, useEffect, useState } from 'react';
import StorageContext, { StorageContextData } from './StorageContext';

interface UseStorageProps<T> {
key: string;
initialValue?: T | undefined;
}

// useStorage<T = string>: A generic function that accepts a UseStorageProps<T> object.
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>;

// 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;
});
Comment on lines +15 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this and use item[key] directly instead of 'storedValue'


// 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 item from local storage and set the stored value to undefined
const clearItem = () => {
removeItem(key);
setStoredValue(undefined)
};
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved

return [storedValue!, setItem, clearItem];
stephane-segning marked this conversation as resolved.
Show resolved Hide resolved
}
9 changes: 7 additions & 2 deletions power-pay-frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
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>
<App />
<StorageProvider storageService={storageService}>
<App />
</StorageProvider>
</React.StrictMode>,
)
)
Loading