import { useReducer } from 'preact/hooks' type DefaultItem = { id: number } const ADD = 'add' type AddAction = { type: typeof ADD payload: I } const add = (item: I): AddAction => ({ type: ADD, payload: item, }) const DEL = 'delete' type DeleteAction = { type: typeof DEL id: number } const del = (id: number): DeleteAction => ({ type: DEL, id, }) const LOAD = 'load' type LoadAction = { type: typeof LOAD payload: I[] } const load = (items: I[]): LoadAction => ({ type: LOAD, payload: items, }) const RESET = 'reset' type ResetAction = { type: typeof RESET payload: I[] } const reset = (items: I[] = []): ResetAction => ({ type: RESET, payload: items, }) const UPDATE = 'update' type UpdateAction = { type: typeof UPDATE id: number payload: I } const update = (id: number, item: I): UpdateAction => ({ type: UPDATE, id, payload: item, }) export const actions = { add, del, load, reset, update, } type Action = AddAction | DeleteAction | LoadAction | ResetAction | UpdateAction export const itemsReducer = (state: I[], action: Action) => { switch (action.type) { case ADD: return [...state, action.payload] case DEL: { const index = state.findIndex((item) => item.id === action.id) if (index > -1) { return [...state.slice(0, index), ...state.slice(index + 1)] } return state } case LOAD: { return [...state, ...action.payload] } case RESET: { return [...action.payload] } case UPDATE: { const index = state.findIndex((item) => item.id === action.id) if (index > -1) { const newItem = { ...state[index], ...action.payload, } return [...state.slice(0, index), newItem, ...state.slice(index + 1)] } return state } default: return state } } export default (init: I[] = []) => { const [items, dispatch] = useReducer(itemsReducer, init) const actions = { add: (item: I) => dispatch(add(item)), del: (id: number) => dispatch(del(id)), load: (items: I[]) => dispatch(load(items)), reset: (items: I[]) => dispatch(reset(items)), update: (id: number, item: I) => dispatch(update(id, item)), } return [items, actions] as [I[], typeof actions] }