A more-or-less entirely reverse-engineered version of Formik, with a hooks-focused API and no use of React's context API.
Malform is meant as an exercise in API and library design, as well as a means to better understanding how libraries like Formik work.
npm install malform
// Validation can be asynchronous, if you need to make a network call.
const validate = (values: LoginForm) => {
return sleep(500).then(() => {
const errors: Partial<{ [e in keyof LoginForm]: string }> = {};
if (["admin", "null", "god"].includes(values.username)) {
errors.username = "Nice try";
}
// ...
return errors;
});
};
// Submission can be similarly be async, but it isn't necessary.
const onSubmit = async (v: LoginForm) => {
await sleep(300);
console.log(v);
};
const App: React.FC = () => {
// Supply initial values, an onSubmit function, and optionally a validation function
// to the useForm hook.
const {
bindForm,
isSubmitting,
isValidating,
bindField,
} = useForm({
initialValues,
onSubmit,
validate,
});
// Bind the appropriate functions to your form elements, using paths
// to the field in your initialValues object.
// Array and object syntax works, so
// {...bindField("details.pets.cats[4].name")}
// and the like will work fine.
return (
<div>
<form
{...bindForm}
style={{
display: "flex",
flexDirection: "column",
width: 300,
padding: "1em",
}}
>
<label htmlFor="username">
Username
<input name="username" {...bindField("username")} />
</label>
<label htmlFor="password">
Password
<input name="password" {...bindField("password")} />
</label>
<label htmlFor="rememberMe">
Remember me?
<input
type="checkbox"
name="rememberMe"
{...bindField("rememberMe")}
/>
</label>
)
}