fix: async validate out of order

This commit is contained in:
Dan Ribbens
2022-12-16 16:45:38 -05:00
parent 0fbfe149df
commit e913fbe4ea
4 changed files with 32 additions and 41 deletions

View File

@@ -19,7 +19,6 @@ type Args = {
state: Fields
path: string
passesCondition: boolean
fieldPromises: Promise<void>[]
id: string | number
operation: 'create' | 'update'
data: Data
@@ -36,7 +35,6 @@ export const addFieldStatePromise = async ({
passesCondition,
fullData,
data,
fieldPromises,
id,
operation,
t,
@@ -81,7 +79,7 @@ export const addFieldStatePromise = async ({
case 'array': {
const arrayValue = Array.isArray(valueWithDefault) ? valueWithDefault : [];
arrayValue.forEach((row, i) => {
const promises = arrayValue.map((row, i) => {
const rowPath = `${path}${field.name}.${i}.`;
state[`${rowPath}id`] = {
value: row.id,
@@ -89,14 +87,13 @@ export const addFieldStatePromise = async ({
valid: true,
};
iterateFields({
return iterateFields({
state,
fields: field.fields,
data: row,
parentPassesCondition: passesCondition,
path: rowPath,
user,
fieldPromises,
fullData,
id,
locale,
@@ -105,6 +102,8 @@ export const addFieldStatePromise = async ({
});
});
await Promise.all(promises);
// Add values to field state
fieldState.value = arrayValue.length;
fieldState.initialValue = arrayValue.length;
@@ -122,6 +121,7 @@ export const addFieldStatePromise = async ({
case 'blocks': {
const blocksValue = Array.isArray(valueWithDefault) ? valueWithDefault : [];
const promises = [];
blocksValue.forEach((row, i) => {
const block = field.blocks.find((blockType) => blockType.slug === row.blockType);
const rowPath = `${path}${field.name}.${i}.`;
@@ -145,7 +145,7 @@ export const addFieldStatePromise = async ({
valid: true,
};
iterateFields({
promises.push(iterateFields({
state,
fields: block.fields,
data: row,
@@ -155,12 +155,12 @@ export const addFieldStatePromise = async ({
user,
locale,
operation,
fieldPromises,
id,
t,
});
}));
}
});
await Promise.all(promises);
// Add values to field state
fieldState.value = blocksValue.length;
@@ -177,11 +177,10 @@ export const addFieldStatePromise = async ({
}
case 'group': {
iterateFields({
await iterateFields({
state,
id,
operation,
fieldPromises,
fields: field.fields,
data: data?.[field.name],
fullData,
@@ -207,14 +206,13 @@ export const addFieldStatePromise = async ({
}
} else if (fieldHasSubFields(field)) {
// Handle field types that do not use names (row, etc)
iterateFields({
await iterateFields({
state,
fields: field.fields,
data,
parentPassesCondition: passesCondition,
path,
user,
fieldPromises,
fullData,
id,
locale,
@@ -222,21 +220,20 @@ export const addFieldStatePromise = async ({
t,
});
} else if (field.type === 'tabs') {
field.tabs.forEach((tab) => {
iterateFields({
state,
fields: tab.fields,
data: tabHasName(tab) ? data?.[tab.name] : data,
parentPassesCondition: passesCondition,
path: tabHasName(tab) ? `${path}${tab.name}.` : path,
user,
fieldPromises,
fullData,
id,
locale,
operation,
t,
});
});
const promises = field.tabs.map((tab) => iterateFields({
state,
fields: tab.fields,
data: tabHasName(tab) ? data?.[tab.name] : data,
parentPassesCondition: passesCondition,
path: tabHasName(tab) ? `${path}${tab.name}.` : path,
user,
fullData,
id,
locale,
operation,
t,
}));
await Promise.all(promises);
}
};

View File

@@ -27,10 +27,9 @@ const buildStateFromSchema = async (args: Args): Promise<Fields> => {
} = args;
if (fieldSchema) {
const fieldPromises = [];
const state: Fields = {};
iterateFields({
await iterateFields({
state,
fields: fieldSchema,
id,
@@ -38,15 +37,12 @@ const buildStateFromSchema = async (args: Args): Promise<Fields> => {
operation,
path: '',
user,
fieldPromises,
data: fullData,
fullData,
parentPassesCondition: true,
t,
});
await Promise.all(fieldPromises);
return state;
}

View File

@@ -16,13 +16,12 @@ type Args = {
path: string
user: User
locale: string
fieldPromises: Promise<void>[]
id: string | number
operation: 'create' | 'update'
t: TFunction
}
export const iterateFields = ({
export const iterateFields = async ({
fields,
data,
parentPassesCondition,
@@ -31,18 +30,17 @@ export const iterateFields = ({
user,
locale,
operation,
fieldPromises,
id,
state,
t,
}: Args): void => {
}: Args): Promise<void> => {
const promises = [];
fields.forEach((field) => {
const initialData = data;
if (!fieldIsPresentationalOnly(field) && !field?.admin?.disabled) {
const passesCondition = Boolean((field?.admin?.condition ? field.admin.condition(fullData || {}, initialData || {}) : true) && parentPassesCondition);
fieldPromises.push(addFieldStatePromise({
promises.push(addFieldStatePromise({
fullData,
id,
locale,
@@ -50,7 +48,6 @@ export const iterateFields = ({
path,
state,
user,
fieldPromises,
field,
passesCondition,
data,
@@ -58,4 +55,5 @@ export const iterateFields = ({
}));
}
});
await Promise.all(promises);
};

View File

@@ -38,7 +38,7 @@ const Upload: React.FC<Props> = (props) => {
const collection = collections.find((coll) => coll.slug === relationTo);
const memoizedValidate = useCallback((value, options) => {
const memoizedValidate = useCallback(async (value, options) => {
return validate(value, { ...options, required });
}, [validate, required]);