This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
p61-project/presentation/presenters/_Presenter.ts

56 lines
1.5 KiB
TypeScript
Raw Normal View History

2024-03-15 22:48:28 +01:00
import { produce } from "immer"
type Listener<State> = (state: State) => void
2024-03-15 22:48:28 +01:00
type SetStateAction<State> = (state: State) => void
2024-03-15 22:48:28 +01:00
export const FETCH_STATES = ["idle", "loading", "error", "success"] as const
export type FetchState = (typeof FETCH_STATES)[number]
2024-03-15 22:48:28 +01:00
export type ErrorGlobal = "unknown" | null
export abstract class Presenter<State> {
private _state: State
private readonly _initialState: State
private readonly _listeners: Array<Listener<State>>
public constructor(initialState: State) {
2024-03-15 22:48:28 +01:00
this._state = initialState
this._initialState = initialState
this._listeners = []
}
public get initialState(): State {
2024-03-15 22:48:28 +01:00
return this._initialState
}
/**
* @description Set the state of the presenter.
* @param action A function that receives the current state and can update it by mutating it.
* @returns The new state.
*/
public setState(action: SetStateAction<State>): State {
2024-03-15 22:48:28 +01:00
this._state = produce(this._state, action)
this.notifyListeners()
return this._state
}
public subscribe(listener: Listener<State>): void {
2024-03-15 22:48:28 +01:00
this._listeners.push(listener)
}
public unsubscribe(listener: Listener<State>): void {
2024-03-15 22:48:28 +01:00
const listenerIndex = this._listeners.indexOf(listener)
const listenerFound = listenerIndex !== -1
if (listenerFound) {
this._listeners.splice(listenerIndex, 1)
}
}
private notifyListeners(): void {
for (const listener of this._listeners) {
listener(this._state)
}
}
}