UNPKG

syncbasestore

Version:

Lightweight reactive store with built-in filtering and async state handling

61 lines (60 loc) 1.86 kB
import { useCallback, useEffect, useState } from 'react'; import { getSyncBase } from '../store/createSyncBase'; export function useBuildBase(tileKey, validators, options) { const base = getSyncBase(); const [fields, setFields] = useState({}); const setField = useCallback((field, rawValue) => { const validator = validators[field]; const { status, message } = validator ? validator(rawValue) : { status: 'idle', message: undefined }; const newField = { valueField: rawValue, status, message, }; base.setState(prev => ({ ...prev, [tileKey]: { ...prev[tileKey], [field]: newField, }, })); setFields(prev => ({ ...prev, [field]: newField, })); }, [base, tileKey, validators]); useEffect(() => { return () => { if (options?.clearOnUnmount) { base.setState(prev => ({ ...prev, [tileKey]: options.initialState ?? {} })); } }; }, [base, tileKey, options]); const overallStatus = (() => { const vals = Object.values(fields); if (vals.some(f => f.status === 'error')) return 'error'; if (vals.some(f => f.status === 'warning')) return 'warning'; if (vals.every(f => f.status === 'success')) return 'success'; return 'idle'; })(); const invalidFields = Object.entries(fields) .filter(([_, v]) => v.status === 'error') .reduce((acc, [k, v]) => { acc[k] = v.message ?? ''; return acc; }, {}); return { setField, fields, overallStatus, invalidFields, }; }