Last active
September 13, 2021 12:05
-
-
Save flpsoares/9b5db12d1eb1cde5157952239edd041e to your computer and use it in GitHub Desktop.
Collection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare namespace App { | |
export interface Model { | |
id: number | |
created_at: Date | |
updated_at: Date | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { TypedEmitter } from 'tiny-typed-emitter' | |
export class Collection<T = any> extends TypedEmitter<{ | |
forceUpdate: () => void | |
}> { | |
private collection: T[] = [] | |
private primaryKey: string = 'id' | |
public addMany(items: T[]) { | |
for (const item of items) { | |
this.set(item) | |
} | |
} | |
public set(item: Partial<T>) { | |
if (this.exists(this.getPrimaryKey(item))) { | |
this.update(item) | |
} else { | |
this.add(item) | |
} | |
this.forceUpdate() | |
} | |
public all() { | |
return this.collection | |
} | |
public add(item: Partial<T>) { | |
// @ts-ignore | |
this.collection.push(item) | |
return item | |
} | |
public update(item: Partial<T>) { | |
const findedItem = this.findByPrimaryKey(this.getPrimaryKey(item)) | |
for (const keyItem in item) { | |
findedItem[keyItem] = item[keyItem] | |
} | |
return findedItem | |
} | |
public delete(primaryKey: any) { | |
this.collection = this.collection.filter((item) => { | |
return this.getPrimaryKey(item) !== primaryKey | |
}) | |
this.forceUpdate() | |
} | |
public forceUpdate() { | |
this.emit('forceUpdate') | |
} | |
public exists(primaryKey: any) { | |
return !!this.findByPrimaryKey(primaryKey) | |
} | |
public findByPrimaryKey(primaryKey: any) { | |
return this.collection.find((item) => { | |
return this.getPrimaryKey(item) === primaryKey | |
}) | |
} | |
private getPrimaryKey(item: Partial<T>) { | |
return item[this.primaryKey] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useMemo, useState } from 'react' | |
import { Collection } from '../services/helpers/Collection' | |
import useDebounce from './helpers/useDebounce' | |
export function useCollection<T>(collection: Collection<T>) { | |
const [lastUpdate, setLastUpdate] = useState<number>(0) | |
const lastUpdateDebounce = useDebounce(lastUpdate, 500) | |
const items = useMemo(() => { | |
return collection.all() | |
}, [lastUpdateDebounce]) | |
const onForceUpdate = () => { | |
setLastUpdate(Date.now()) | |
} | |
useEffect(() => { | |
collection.on('forceUpdate', onForceUpdate) | |
return () => { | |
collection.off('forceUpdate', onForceUpdate) | |
} | |
}, []) | |
return { items } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from 'react' | |
function useDebounce<T>(value: T, delay?: number): T { | |
const [debouncedValue, setDebouncedValue] = useState<T>(value) | |
useEffect(() => { | |
const timer = setTimeout(() => setDebouncedValue(value), delay || 500) | |
return () => { | |
clearTimeout(timer) | |
} | |
}, [value, delay]) | |
return debouncedValue | |
} | |
export default useDebounce |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare namespace App { | |
export interface User extends App.Model { | |
username: string | |
password: string | |
email?: string | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { api } from '../api' | |
import UsersCollection from '../collections/UsersCollection' | |
class UserApi { | |
public async create({ username, password, email }: Partial<App.User>) { | |
return api.post('user', { | |
username, | |
password, | |
}) | |
} | |
public async list() { | |
return api | |
.get<App.User[]>('users') | |
.then((res) => res.data) | |
.then((users) => { | |
UsersCollection.addMany(users) | |
return users | |
}) | |
} | |
public async delete(user: App.User) { | |
return api.delete(`user/${user.id}`).then(() => { | |
UsersCollection.delete(user.id) | |
}) | |
} | |
} | |
export default new UserApi() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Collection } from '../helpers/Collection' | |
class UsersCollection extends Collection<App.User> {} | |
export default new UsersCollection() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment