syncbasestore
Version:
Lightweight reactive store with built-in filtering and async state handling
61 lines (60 loc) • 1.86 kB
JavaScript
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,
};
}