import { useEffect, useState } from 'react'; import { BaseModel, CHANGE_EVENT_TYPE, EventTopic } from '../models'; import { HasOne } from '../models/has-one'; import { Id } from '../types'; import { useAsync, UseAsyncResult } from './use-async'; import { useBaseModelRelation, useSDKEventBus } from './use-models'; export type UseHasOne = { model: any; getByParentId: (parentId: Id) => UseAsyncResult; createByParentId: (parentId: Id) => UseAsyncResult; }; export const useHasOne = ( model: BaseModel, classProp: string, ) => { const relation = useBaseModelRelation(model, classProp); const eventBus = useSDKEventBus(); return { model: relation, getByParentId: useGetByParentId(relation, eventBus), createByParentId: useCreateByParentId(relation, eventBus), }; }; const useGetByParentId = ( relation: HasOne, eventBus: EventTopic, ) => (parentId: Id): UseAsyncResult => { const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync(relation.get.bind(relation)); async function handleChange() { const d = await relation.getLocal(parentId); setData(d); } useEffect(() => { handleChange(); }, []); useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }); useEffect(() => { setData(gotten); }, [gotten]); const exec = (...args: any[]) => fetch(parentId, ...args); return [data, exec, loading, error]; }; const useCreateByParentId = ( relation: HasOne, eventBus: EventTopic, ) => (parentId: Id): UseAsyncResult => { const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync( relation.create.bind(relation), ); async function handleChange() { setData(await relation.getLocal(parentId)); } useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }); useEffect(() => { setData(gotten); }, [gotten]); const exec = (...args: any[]) => fetch(parentId, ...args); return [data, exec, loading, error]; };