👔 Elegant form management primitives for the react hooks era.
yarn add @kevinwolf/formal
Note: this boilerplate can be reduced.
import React from "react";
import * as yup from "yup";
import useFormal from "@kevinwolf/formal";
const schema = yup.object().shape({
firstName: yup.string().required(),
lastName: yup.string().required(),
email: yup
.string()
.email()
.required()
});
const initialValues = {
firstName: "Tony",
lastName: "Stark",
email: "ironman@avengers.io"
};
export default function App() {
const formal = useFormal(initialValues, {
schema,
onSubmit: values => console.log("Your values are:", values)
});
const handleSubmit = e => {
e.preventDefault();
formal.submit();
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<input
type="text"
id="firstName"
name="firstName"
value={formal.values.firstName}
onChange={e => formal.change("firstName", e.target.value)}
/>
{formal.errors.firstName && <div>{formal.errors.firstName}</div>}
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<input
type="text"
id="lastName"
name="lastName"
value={formal.values.lastName}
onChange={e => formal.change("lastName", e.target.value)}
/>
{formal.errors.lastName && <div>{formal.errors.lastName}</div>}
</div>
<div>
<label htmlFor="email">Email</label>
<input
type="text"
id="email"
name="email"
value={formal.values.email}
onChange={e => formal.change("email", e.target.value)}
/>
{formal.errors.email && <div>{formal.errors.email}</div>}
</div>
<button type="submit">Submit</button>
</form>
);
}
import React from "react";
import { View, Text, TextInput, Button } from "react-native";
import * as yup from "yup";
import useFormal from "@kevinwolf/formal";
const schema = yup.object().shape({
firstName: yup.string().required(),
lastName: yup.string().required(),
email: yup
.string()
.email()
.required()
});
const initialValues = {
firstName: "Tony",
lastName: "Stark",
email: "ironman@avengers.io"
};
export default function App() {
const formal = useFormal(initialValues, {
schema,
onSubmit: values => console.log("Your values are:", values)
});
return (
<View>
<View>
<Text>First Name</Text>
<TextInput
value={formal.values.firstName}
onChangeText={text => formal.change("firstName", text)}
/>
{formal.errors.firstName && <Text>{formal.errors.firstName}</Text>}
</View>
<View>
<Text>Last Name</Text>
<TextInput
value={formal.values.lastName}
onChangeText={text => formal.change("lastName", text)}
/>
{formal.errors.lastName && <Text>{formal.errors.lastName}</Text>}
</View>
<View>
<Text>Email</Text>
<TextInput
value={formal.values.email}
onChangeText={text => formal.change("email", text)}
/>
{formal.errors.email && <Text>{formal.errors.email}</Text>}
</View>
<Button onPress={formal.submit} title="Submit" />
</View>
);
}
In order to reduce boilerplate, you can install one of two packages depending on whether you are on web or mobile. That way, you will receive some prop getters that you just have to spread to your inputs and buttons. ✨
For extended documentation, examples and contributing guidelines, please refer to the monorepo containing this package.