Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

Commit

Permalink
feat(useForm): support built-in validation
Browse files Browse the repository at this point in the history
  • Loading branch information
wellyshen committed Nov 11, 2020
1 parent 1d013bb commit ab72fdb
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/silly-bobcats-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-cool-form": patch
---

feat(useForm): support built-in validation
3 changes: 3 additions & 0 deletions examples/src/BasicForm/Controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface Props {
defaultValue: any;
controller: ControllerType<FormValues, ChangeEvent<HTMLInputElement>>;
validate?: FieldValidator<FormValues>;
[k: string]: any;
}

const Controller = ({
Expand All @@ -25,6 +26,7 @@ const Controller = ({
defaultValue,
controller,
validate,
...rest
}: Props) => {
// console.log(`LOG ==> ${name} is re-rendered`);

Expand All @@ -48,6 +50,7 @@ const Controller = ({
// console.log("LOG ===> onBlur: ", e);
},
})}
{...rest}
/>
);
};
Expand Down
14 changes: 8 additions & 6 deletions examples/src/BasicForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export interface FormValues {
}

const initialValues = {
text: { nest: "test" },
controller: "test",
text: { nest: "" },
controller: "",
hiddenText: "test",
password: "test",
number: 5,
Expand Down Expand Up @@ -203,11 +203,12 @@ export default (): JSX.Element => {
<Input
label="Text:"
name="text.nest"
ref={validate(async (value) => {
/* ref={validate(async (value) => {
// eslint-disable-next-line
// await new Promise((resolve) => setTimeout(resolve, 1000));
return value.length <= 5 ? "Field error" : "";
})}
})} */
// required
// data-rcf-ignore
/>
<Controller
Expand All @@ -221,15 +222,16 @@ export default (): JSX.Element => {
// console.log("LOG ===> validate: ", val, values);
return val.length <= 5 ? "Field error" : "";
}, [])} */
maxLength="3"
/>
{showInput && (
<div>
<Input
label="Hidden Text:"
name="hiddenText"
ref={validate(async (value) => {
/* ref={validate(async (value) => {
return value.length <= 5 ? "Field error" : "";
})}
})} */
/>
</div>
)}
Expand Down
52 changes: 39 additions & 13 deletions src/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,23 @@ const useForm = <V extends FormValues = FormValues>({
[setErrors, setStateRef, stateRef]
);

const runBuiltInValidation = useCallback(
(name: string) =>
fieldsRef.current[name] &&
fieldsRef.current[name].field.validationMessage,
[]
);

const runAllBuiltInsValidation = useCallback(
() =>
Object.keys(fieldsRef.current).reduce((errors, name) => {
const error = runBuiltInValidation(name);
errors = { ...errors, ...(error ? set({}, name, error) : {}) };
return errors;
}, {}),
[runBuiltInValidation]
);

const runFieldValidation = useCallback(
async (name: string): Promise<any> => {
if (!fieldValidatorsRef.current[name]) return undefined;
Expand All @@ -246,10 +263,9 @@ const useForm = <V extends FormValues = FormValues>({
const promises = Object.keys(fieldValidatorsRef.current).map((name) =>
runFieldValidation(name)
);
const names = Object.keys(fieldValidatorsRef.current);

return Promise.all(promises).then((errors) =>
names.reduce((acc, cur, idx) => {
Object.keys(fieldValidatorsRef.current).reduce((acc, cur, idx) => {
acc = { ...acc, ...(errors[idx] ? set({}, cur, errors[idx]) : {}) };
return acc;
}, {})
Expand Down Expand Up @@ -283,7 +299,9 @@ const useForm = <V extends FormValues = FormValues>({

try {
const error =
(await runFormValidation(name)) || (await runFieldValidation(name));
(await runFormValidation(name)) ||
(await runFieldValidation(name)) ||
runBuiltInValidation(name);

if (error) setStateRef(`errors.${name}`, error);
setStateRef("isValidating", false);
Expand All @@ -292,21 +310,29 @@ const useForm = <V extends FormValues = FormValues>({
return exception;
}
},
[runFieldValidation, runFormValidation, setStateRef]
[runBuiltInValidation, runFieldValidation, runFormValidation, setStateRef]
);

const validateForm = useCallback<ValidateForm<V>>(() => {
setStateRef("isValidating", true);

return Promise.all([runAllFieldsValidation(), runFormValidation()]).then(
(errors) => {
const errs = deepMerge(...errors);
setErrors(errs);
setStateRef("isValidating", false);
return errs;
}
);
}, [runAllFieldsValidation, runFormValidation, setErrors, setStateRef]);
return Promise.all([
runAllBuiltInsValidation(),
runAllFieldsValidation(),
runFormValidation(),
]).then((errors) => {
const errs = deepMerge(...errors);
setErrors(errs);
setStateRef("isValidating", false);
return errs;
});
}, [
runAllBuiltInsValidation,
runAllFieldsValidation,
runFormValidation,
setErrors,
setStateRef,
]);

const validateFormWithLowPriority = useCallback(
() =>
Expand Down

0 comments on commit ab72fdb

Please sign in to comment.