Skip to content

Commit

Permalink
Remove SubmitValidationError in favor of plain SubmitResult object
Browse files Browse the repository at this point in the history
  • Loading branch information
10xjs committed Jul 7, 2021
1 parent 1c0bd95 commit 4634fe5
Show file tree
Hide file tree
Showing 9 changed files with 20 additions and 340 deletions.
4 changes: 2 additions & 2 deletions docs/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ const ExampleForm = () => {
};
```

Validation errors can also be returned from the [`onSubmit` handler](/docs/api/interfaces/formoptions#onsubmit) by returning a [`SubmitValidationError`](/docs/api/classes/submitvalidationerror) instance. This provides a mechanism to integrate API validation errors and to handle more expensive or async local validation operations.
Validation errors can also be returned from the [`onSubmit` handler](/docs/api/interfaces/formoptions#onsubmit) by returning a failing [`SubmitResult`](/docs/api/types/submitresult) object containing `{ok: false, errors: [validation errors]}`. This provides a mechanism to integrate API validation errors and to handle more expensive or async local validation operations.

The `onSubmit` callback must return a [`SubmitResult`](/docs/api/types/submitresult) value (or a `Promise` resolving a `SubmitResult` value) with `ok` and `data`/`error` properties.

Expand All @@ -241,7 +241,7 @@ const ExampleForm = () => {
}

if (Object.keys(errors).length) {
return {ok: false, error: new SubmitValidationError(errors)};
return {ok: false, errors};
}

return {ok: true};
Expand Down
5 changes: 0 additions & 5 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ module.exports = {
label: 'FormState',
href: '/docs/api/classes/formstate',
},
{
type: 'link',
label: 'SubmitValidationError',
href: '/docs/api/classes/submitvalidationerror',
},
],
Recipes: ['persistent-state', 'multi-step-forms'],
},
Expand Down
30 changes: 0 additions & 30 deletions packages/form/src/core/errors.ts

This file was deleted.

21 changes: 1 addition & 20 deletions packages/form/src/core/formState.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {FormState} from './formState';
import {SubmitValidationError} from './errors';

describe('FormStateManager', () => {
describe('constructor', () => {
Expand All @@ -25,7 +24,6 @@ describe('FormStateManager', () => {
expect(state.visitedMap).toEqual({});
expect(state.submitStatus).toBe('INITIAL');
expect(state.result).toBeUndefined();
expect(state.error).toBeUndefined();
});

it('should run validate and warn', () => {
Expand Down Expand Up @@ -407,7 +405,7 @@ describe('FormStateManager', () => {
const values = {foo: 'bar'};
const form = new FormState(values, {
onSubmit() {
return {ok: false, error: new SubmitValidationError({foo: 'error'})};
return {ok: false, errors: {foo: 'error'}};
},
});

Expand Down Expand Up @@ -542,22 +540,5 @@ describe('FormStateManager', () => {

expect(form.getState().result).toEqual('result');
});

it('should handle error result', async () => {
const submitError = new Error();

const form = new FormState(
{},
{
onSubmit() {
return {ok: false, error: submitError};
},
},
);

await expect(form.submit()).resolves.toBeUndefined();

expect(form.getState().error).toEqual(submitError);
});
});
});
50 changes: 13 additions & 37 deletions packages/form/src/core/formState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {set, get, normalizeError, formatPath, parsePath, equals} from './utils';
import {StateManager} from './stateManager';
import {SubmitError, SubmitValidationError} from './errors';

/**
* The path to a field within the form state as either a string or an array.
Expand Down Expand Up @@ -72,28 +71,29 @@ export interface FormData<VS, SD = unknown, ES = undefined, WS = undefined> {
visitedMap: Record<string, boolean>;
submitStatus: FormSubmitStatus;
result?: SD;
error?: SubmitError;
}

/**
* @typeParam SD Type of submit handler result.
* @typeParam ES Type of form error state.
*/
export type SubmitResult<SD = unknown> =
export type SubmitResult<SD = unknown, ES = unknown> =
| (unknown extends SD ? {ok: true; data?: SD} : {ok: true; data: SD})
| {ok: false; error: SubmitError};
| {ok: false; errors: ES};

/**
* @typeParam VS Type of form value state.
* @typeParam SD Type of submit handler result.
* @typeParam ES Type of form error state.
*/
export type SubmitHandler<VS, SD = unknown> = (
export type SubmitHandler<VS, SD = unknown, ES = unknown> = (
values: VS,
) => // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
| void
| undefined
| SubmitResult<SD>
| SubmitResult<SD, ES>
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
| Promise<void | undefined | SubmitResult<SD>>;
| Promise<void | undefined | SubmitResult<SD, ES>>;

/**
* @typeParam VS Type of form value state.
Expand Down Expand Up @@ -139,7 +139,7 @@ export interface FormOptions<VS, SD = unknown, ES = undefined, WS = undefined> {
* };
* ```
*/
onSubmit: SubmitHandler<VS, SD>;
onSubmit: SubmitHandler<VS, SD, ES>;

/**
* Run error validation on the entire value state. This handler is triggered
Expand Down Expand Up @@ -299,7 +299,6 @@ export class FormState<
visitedMap: {},
submitStatus: FormSubmitStatus.initial,
result: undefined,
error: undefined,
});

this._config = config;
Expand Down Expand Up @@ -558,14 +557,10 @@ export class FormState<
this._set(['submitStatus'], FormSubmitStatus.started);
}

private _submitFailed(error?: SubmitError) {
if (error instanceof SubmitValidationError) {
this._set(['submitErrors'], normalizeError(error.errors));
}

private _submitFailed(errors?: ES) {
this._set(['submitErrors'], normalizeError(errors));
this._set(['submitStatus'], FormSubmitStatus.failed);
this._set(['result'], undefined);
this._set(['error'], error);
}

private _submitEnded(data?: SD) {
Expand All @@ -583,7 +578,7 @@ export class FormState<
*/
submit() {
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
return new Promise<void | undefined | SubmitResult<SD>>((resolve) => {
return new Promise<void | undefined | SubmitResult<SD, ES>>((resolve) => {
const {submitStatus, errors, values} = this._getNextState();

if (submitStatus === FormSubmitStatus.started) {
Expand All @@ -596,7 +591,7 @@ export class FormState<
this._flush();

if (errors !== undefined) {
return resolve({ok: false, error: new SubmitValidationError(errors)});
return resolve({ok: false, errors});
}

return resolve(this._config.onSubmit(values));
Expand All @@ -607,7 +602,7 @@ export class FormState<
} else if (result.ok) {
this._submitEnded(result.data);
} else {
this._submitFailed(result.error);
this._submitFailed(result.errors);
}

this._flush();
Expand Down Expand Up @@ -657,25 +652,6 @@ export class FormState<
return this.getWarnings() !== undefined;
}

/**
* Get the current submit error.
*
* ```js {9}
* const form = new FormState({}, {
* async onSubmit(values) {
* return {ok: false, error: new SubmitValidationError({...})};
* }
* };
*
* await form.submit();
*
* form.getError(); // SubmitValidationError
* ```
*/
getError() {
return this.getState().error;
}

getResult() {
return this.getState().result;
}
Expand Down
6 changes: 0 additions & 6 deletions packages/form/src/core/formStatus.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {SubmitError} from './errors';
import {FormState, FormSubmitStatus} from './formState';
import {StateManager, Subscription} from './stateManager';
import {set} from './utils';
Expand Down Expand Up @@ -28,10 +27,6 @@ export interface FormStatusData<SR> {
* True if any field validation warnings currently exist.
*/
hasWarnings: boolean;
/**
* Submit result error.
*/
error: SubmitError | null;
/**
* Submit result.
*/
Expand Down Expand Up @@ -69,7 +64,6 @@ export class FormStatus<SR> extends StateManager<FormStatusData<SR>> {
nextState = set(nextState, ['hasSubmitErrors'], form.hasSubmitErrors());
nextState = set(nextState, ['hasWarnings'], form.hasWarnings());

nextState = set(nextState, ['error'], form.getError());
nextState = set(nextState, ['result'], form.getResult());

return nextState as FormStatusData<SR>;
Expand Down
1 change: 0 additions & 1 deletion packages/form/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './core/errors';
export * from './core/field';
export * from './core/fieldStatus';
export * from './core/formState';
Expand Down
Loading

0 comments on commit 4634fe5

Please sign in to comment.