Skip to content

Commit

Permalink
Merge pull request #34 from rzane/no-async
Browse files Browse the repository at this point in the history
Trim bundle size by avoiding async/await
  • Loading branch information
rzane authored Oct 1, 2020
2 parents db43474 + 2f45373 commit 16efc68
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 41 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
"size-limit": [
{
"path": "dist/form.esm.js",
"limit": "5 KB"
"limit": "2 KB"
},
{
"path": "dist/form.cjs.production.min.js",
"limit": "5 KB"
"limit": "2 KB"
}
],
"peerDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion src/useReset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import { useEventCallback } from "./utilities/useEventCallback";
* const reset = useReset(form);
*/
export function useReset<Value, Result>(form: Form<Value, Result>): Reset {
return useEventCallback(async (event?: FormEvent<HTMLFormElement>) => {
return useEventCallback((event?: FormEvent<HTMLFormElement>) => {
if (event) {
event.preventDefault();
event.stopPropagation();
}

form.reset();
return Promise.resolve();
});
}
47 changes: 22 additions & 25 deletions src/useSubmit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FormEvent } from "react";
import { Form, Submit } from "./types";
import { toPromise } from "./utilities/toPromise";
import { useMounted } from "./utilities/useMounted";
import { useEventCallback } from "./utilities/useEventCallback";

Expand All @@ -23,43 +24,39 @@ export function useSubmit<Value, Result>(
): Submit {
const isMounted = useMounted();

return useEventCallback(async (event?: FormEvent<HTMLFormElement>) => {
return useEventCallback((event?: FormEvent<HTMLFormElement>) => {
if (event) {
event.preventDefault();
event.stopPropagation();
}

if (form.isSubmitting) {
return;
return Promise.resolve();
}

form.setSubmitting(true);

try {
const result = await form.validate({ touch: true });

if (result.valid) {
await fn(result.value);

return toPromise(() => form.validate({ touch: true }))
.then(result => {
if (!result.valid) return;

return toPromise(() => fn(result.value)).then(() => {
if (isMounted.current) {
form.setSubmission(prev => ({ count: prev.count + 1 }));
}
});
})
.catch(error => {
if (isMounted.current) {
form.setSubmission(prev => ({
count: prev.count + 1
}));
form.setSubmission(prev => ({ count: prev.count + 1, error }));
}
}
} catch (error) {
if (isMounted.current) {
form.setSubmission(prev => ({
count: prev.count + 1,
error
}));
}

throw error;
} finally {
if (isMounted.current) {
form.setSubmitting(false);
}
}
throw error;
})
.finally(() => {
if (isMounted.current) {
form.setSubmitting(false);
}
});
});
}
30 changes: 17 additions & 13 deletions src/useValidation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useMemo } from "react";
import { toPromise } from "./utilities/toPromise";
import { getAllTouched } from "./utilities/getAllTouched";
import { useMounted } from "./utilities/useMounted";
import { useEventCallback } from "./utilities/useEventCallback";
Expand Down Expand Up @@ -31,25 +32,28 @@ export function useValidation<Value, Result>(
const isMounted = useMounted();
const { onChange = true, onBlur = true } = opts;

const validate = useEventCallback(async (opts: ValidateOptions = {}) => {
const validate = useEventCallback((opts: ValidateOptions = {}) => {
form.setValidating(true);

try {
const result = await fn(form.value);
const errors = result.valid ? undefined : result.error;
return toPromise(() => fn(form.value))
.then(result => {
const errors = result.valid ? undefined : result.error;

if (isMounted.current) {
form.setError(errors);
if (isMounted.current) {
form.setError(errors);

if (opts.touch) {
form.setTouched(getAllTouched(errors));
if (opts.touch) {
form.setTouched(getAllTouched(errors));
}
}
}

return result;
} finally {
if (isMounted.current) form.setValidating(false);
}
return result;
})
.finally(() => {
if (isMounted.current) {
form.setValidating(false);
}
});
});

useEffect(() => {
Expand Down
11 changes: 11 additions & 0 deletions src/utilities/toPromise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* If the value returned by the function is not a promise, convert it.
* Make sure to catch errors that are thrown syncronously.
*/
export function toPromise<T>(fn: () => T | PromiseLike<T>): Promise<T> {
try {
return Promise.resolve(fn());
} catch (error) {
return Promise.reject(error);
}
}
32 changes: 32 additions & 0 deletions test/utilities/toPromise.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { toPromise } from "../../src/utilities/toPromise";

describe("toPromise", () => {
test("converts sync success", async () => {
const promise = toPromise(() => 1);
expect(promise).toBeInstanceOf(Promise);
await expect(promise).resolves.toEqual(1);
});

test("converts sync error", async () => {
const promise = toPromise(() => {
throw new Error("boom");
});

expect(promise).toBeInstanceOf(Promise);
await expect(promise).rejects.toThrow(/boom/);
});

test("converts async success", async () => {
const promise = toPromise(() => Promise.resolve(1));

expect(promise).toBeInstanceOf(Promise);
await expect(promise).resolves.toEqual(1);
});

test("converts async error", async () => {
const promise = toPromise(() => Promise.reject(new Error("boom")));

expect(promise).toBeInstanceOf(Promise);
await expect(promise).rejects.toThrow(/boom/);
});
});

0 comments on commit 16efc68

Please sign in to comment.