Skip to content

Instantly share code, notes, and snippets.

@mweibel
Last active January 24, 2020 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mweibel/913f584ee8fbd4970dac461a89cd857b to your computer and use it in GitHub Desktop.
Save mweibel/913f584ee8fbd4970dac461a89cd857b to your computer and use it in GitHub Desktop.
my own useForm hook
const schema = {
email: {
presence: { allowEmpty: false, message: "required" },
email: {
message: "valid"
}
}
};
interface LoginFormFields {
email: string;
}
const { formState, handleChange, hasError } = useForm<LoginFormFields>(schema, { email: "" });
<TextField
name="email"
error={hasError("email")}
fullWidth
helperText={hasError("email") ? t(`form.${formState.errors.email[0]}`) : null}
label={t("form.email")}
required={true}
type="email"
value={formState.values.email || ""}
onChange={handleChange}
disabled={loading}
autoFocus
/>
import { ChangeEvent, useState } from "react";
import validate from "validate.js";
// if you add this validator it will always fail. Useful for custom validations.
validate.validators.fail = function(value: string, options: any) {
return options.message;
};
interface FormStateType {
[name: string]: string | boolean;
}
interface FormStateErrors {
[name: string]: string[];
}
export interface FormState<T> {
isValid: boolean;
values: T;
touched: FormStateType;
errors: FormStateErrors;
}
export const useForm = <T>(schema: any, values: T) => {
const errors = validate(values, schema) || {};
const [formState, setFormState] = useState<FormState<T>>({
isValid: Object.keys(errors).length === 0,
values,
touched: {} as FormStateType,
errors
});
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
event.persist();
setFormState(prevFormState => {
const newState = {
...prevFormState,
values: {
...prevFormState.values,
[event.target.name]: event.target.type === "checkbox" ? event.target.checked : event.target.value
},
touched: {
...prevFormState.touched,
[event.target.name]: true
}
};
newState.errors = validate(newState.values, schema) || {};
newState.isValid = Object.keys(newState.errors).length === 0;
return newState;
});
};
const hasError = (field: string) => !!(formState.touched[field] && formState.errors[field]);
return { formState, handleChange, hasError };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment