π collection of atoms, utility functions and hooks to easily create forms with jotai and react
The docs can be found at https://omnidan.github.io/jotai-advanced-forms/
npm i jotai-advanced-forms
In a directory co-located with the component/page that uses the form, place a state.ts
file, with the following contents:
import { createForm } from "jotai-advanced-forms";
const { formFieldAtom, useForm } = createForm();
export { useForm };
// required field
export const firstNameAtom = formFieldAtom<string, "required">({
initialState: "",
validate: (value) => {
if (value.length === 0) return "required";
},
});
// optional field
export const lastNameAtom = formFieldAtom<string, undefined>({
initialState: "",
});
Then, it is advisable to create custom input components that can deal with the props that this library provides:
import type { UseFormFieldProps } from "jotai-advanced-forms";
export function StringInput({
value,
onChange,
onBlur,
ref,
hasError,
errorCode,
errorText,
}: UseFormFieldProps<string>) {
return (
<div>
<input
value={value}
onChange={(e) => onChange(e.target.value)}
onBlur={onBlur}
ref={ref}
/>
{hasError && (
<p>
{errorText} ({errorCode})
</p>
)}
</div>
);
}
Now, in a React component that contains the form, you can do the following:
import { useFormField } from "jotai-advanced-forms";
import { firstNameAtom, lastNameAtom, useForm } from "./state.js";
import { StringInput } from "./StringInput.js";
export function NameInputForm() {
const firstNameField = useFormField({
atom: firstNameAtom,
errors: {
// if you do not specify this, it will cause a type error, forcing you to handle error messages!
required: "First name is required!",
},
});
const lastNameField = useFormField({
atom: lastNameAtom,
});
const { submitForm, isSubmitting } = useForm({
onValid: () => alert("success!"),
});
function handleSubmit(e) {
e.preventDefault();
submitForm();
}
return (
<form onSubmit={handleSubmit}>
<StringInput {...firstNameField} />
<StringInput {...lastNameField} />
<input type="submit" value="Submit" disabled={isSubmitting} />
</form>
);
}
See .github/CONTRIBUTING.md
, then .github/DEVELOPMENT.md
.
Thanks! π
π This package was templated with
create-typescript-app
using thecreate
engine.