Skip to content

Commit d799745

Browse files
committed
Simpler getting started
1 parent 422804c commit d799745

File tree

7 files changed

+53
-52
lines changed

7 files changed

+53
-52
lines changed

articles/Getting-started.md

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ This library works with both **Javascript** and **Typescript**. Typescript is ce
1717

1818
### Using the `useForm` hook
1919

20-
A form always starts with the `useForm` hook call, this function returns a form state manager ([FormState](/docs/FormState)), which you must then pass to all your inputs (this is required for type-checking).
21-
22-
All of the form hook ([`useForm`](/docs/useForm), [`useChildForm`](/docs/useChildForm) ...) must be called, unconditionally, at the start of your component, just like the normal React hooks.
20+
A form always starts with the `useForm` hook call, this function returns a form state manager ([FormState](/docs/FormState)), which you must then pass to all your inputs.
2321

2422
✔️ **Importing and using `useForm`**
2523

@@ -34,8 +32,7 @@ function MyForm() {
3432

3533
### Creating the submit handler
3634

37-
Pass `form.handleSubmit` to the form's `onSubmit` prop to validate before calling your callback function.
38-
You can also just use a `<button>` and submitting in the button's `onClick` handler, but this event does not fire when pressing return/enter in a text input!
35+
Use `form.handleSubmit` to validate before calling your function. It does not get called if there is a validation error, and prevents the page from reloading.
3936

4037
✔️ **`<form>` element with `onSubmit` event**
4138

@@ -44,37 +41,31 @@ import { useForm } from "typed-react-form";
4441

4542
function MyForm() {
4643
const form = useForm({ email: "" });
44+
45+
function submit() {
46+
// The form.handleSubmit validates the form before calling this function
47+
console.log("submit", form.values);
48+
}
49+
4750
// Use the standard html form element, which exposes the onSubmit event.
4851
return (
49-
<form
50-
onSubmit={form.handleSubmit(() => {
51-
// The form.handleSubmit validates the form before calling your callback
52-
// Do your submit logic here...
53-
console.log("submit", form.values);
54-
})}
55-
>
52+
<form onSubmit={form.handleSubmit(submit)}>
5653
{/* Make sure to add type="submit" */}
5754
<button type="submit">Submit!</button>
5855
</form>
5956
);
6057
}
6158
```
6259

63-
`form.handleSubmit()` just returns a helper function that wraps `ev.preventDefault()`, `form.validate()` and `form.setState()`.
64-
6560
### Creating inputs
6661

67-
This library is build upon the fact that only the things that change should rerender (~refresh), for example: when the _name_ field changes, only the inputs that use the _name_ field will rerender.
68-
69-
The built-in form elements ([`FormInput`](/docs/FormInput), [`FormSelect`](/docs/FormSelect) ...) implement this by listening for changes only on their specified field. You can also use multiple inputs on the same field (they will the synchronized) and listen for changes on a field by using the [`useListener`](/docs/useListener) hook or [`Listener`](/docs/Listener) component.
70-
71-
You are now ready to create inputs, this library provides the following built-in components to create type-checked inputs:
62+
This library provides the following built-in components to create type-checked inputs:
7263

7364
- [FormInput](/docs/FormInput)
7465
- [FormSelect](/docs/FormSelect)
7566
- [FormTextArea](/docs/FormTextArea)
7667

77-
**When these inputs do not satisfy your needs**, you can always [create your own](/docs/Custom-inputs#example-custom-input). These built-in components are just abstractions around hook calls.
68+
When these inputs do not satisfy your needs, you can always [implement your own](/docs/Custom-inputs#example-custom-input). These built-in components are just abstractions around hook calls.
7869

7970
✔️ **Example type-checked form consisting of 2 fields**
8071

@@ -84,17 +75,18 @@ import { useForm, FormInput } from "typed-react-form";
8475

8576
function MyForm() {
8677
const form = useForm({ email: "", password: "" });
78+
79+
async function submit() {
80+
// Implement your submit logic here...
81+
console.log("submitting", form.values);
82+
// Fake fetch, by waiting for 500ms
83+
await new Promise((res) => setTimeout(res, 500));
84+
// Optional: set new default values
85+
form.setDefaultValues(form.values);
86+
}
87+
8788
return (
88-
<form
89-
onSubmit={form.handleSubmit(async (ev) => {
90-
// Implement your submit logic here...
91-
console.log("submitting", form.values);
92-
// Fake fetch, by waiting for 500ms
93-
await new Promise((res) => setTimeout(res, 500));
94-
// Optional: set new default values
95-
form.setDefaultValues(form.values);
96-
})}
97-
>
89+
<form onSubmit={form.handleSubmit(submit)}>
9890
{/* Make sure to pass the form prop! */}
9991
<FormInput form={form} name="email" type="text" />
10092
<FormInput form={form} name="password" type="password" />
@@ -104,11 +96,6 @@ function MyForm() {
10496
}
10597
```
10698

107-
**When you have an object or array field**, you need to _unwrap_ this field by using a child/array form. When _unwrapped_ you can use the inputs above.
108-
109-
- [Object fields](/docs/Object-fields)
110-
- [Array fields](/docs/Array-fields)
111-
11299
## Step 3: It's your turn
113100

114101
Tweak the above example to your desire by...

articles/useAnyListener.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Because this library does not rerender the whole form component when a field cha
44

55
The useAnyListener hook listens for any change on a form. Behaves a lot like [`useListener`](/docs/useListener) but does not take a `name` parameter.
66

7+
This hook must be called, unconditionally, at the start of your component, just like the normal React hooks.
8+
79
**To listen to just one field** instead of every field, use the `useListener` hook instead.
810

911
**Use the [`AnyListener` component](/docs/AnyListener) if you want to use these hooks without creating a new component each time.**

articles/useArrayForm.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
A hook that provides array manipulation functions and optimizations for an array field. This is the array-optimized version of [`useChildform`](/docs/useChildForm). This hook only causes a rerender when the array size changes (this is why `values.map((e) => ...)` works when adding/removing a value).
44

5+
This hook must be called, unconditionally, at the start of your component, just like the normal React hooks.
6+
57
**If your array field can/will be null or undefined**, you should use the [`ArrayForm`](/docs/ArrayForm) component instead, which does not render when the array is null/undefined.
68

79
`useArrayForm(parentForm, nameOfArrayField)`

articles/useChildForm.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Creates a form based on another form's field. Use this with nested objects. This hook does not cause a rerender.
44

5+
This hook must be called, unconditionally, at the start of your component, just like the normal React hooks.
6+
57
**If your field can/will be null or undefined**, you should use the [`ChildForm`](/docs/ChildForm) component instead, which does not render when the field is null/undefined.
68

79
`useChildForm(parentForm, name)`

articles/useForm.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Creates a new form state manager. This hook does not cause a rerender.
44

5+
This hook must be called, unconditionally, at the start of your component, just like the normal React hooks.
6+
57
**Note for using `setState` along with `useForm`**: This library is built upon the fact that only the things that change should rerender. When using `setState` with the form, a state change causes the whole form to rerender. You can reduce this problem by creating components from the things that use the state, or you can use [custom form state](/docs/useForm#defaultstate-optional-issubmitting-false).
68

79
`useForm(defaultValues, validator?, validateOnChange = false, validateOnMount = false, defaultState = {isSubmitting: false})`

articles/useListener.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# `useListener`
22

3-
Because this library does not rerender the whole form component when a field changes, there must be a way to get notified about state changes. This is where listeners come in.
3+
This library is build upon the fact that only the things that change should rerender, for example: when the _name_ field changes, only the inputs that use the _name_ field will rerender.
4+
5+
The built-in form elements ([`FormInput`](/docs/FormInput), [`FormSelect`](/docs/FormSelect) ...) implement this by listening for changes only on their specified field. You can also use multiple inputs on the same field (they will the synchronized).
46

57
The useListener hook listens for changes on a specific form field. It behaves like useState. Because this hooks causes a rerender, you **shouldn't** use
68
this hook in the same component as the form it is using (causes the whole form to rerender). You **should** always create a new component which contains the hook and use that. Or use the [`Listener`](/docs/Listener) component, which wraps the `useListener` hook for you.
79

10+
This hook must be called, unconditionally, at the start of your component, just like the normal React hooks.
11+
812
**To listen for all form fields at once**, use the [`useAnyListener`](/docs/useAnyListener) hook instead.
913

1014
**✔️ Right usage**

pages/docs/test.tsx

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ import {
1313

1414
function MyForm() {
1515
const form = useForm({ email: "" });
16+
17+
function submit() {
18+
// The form.handleSubmit validates the form before calling this function
19+
console.log("submit", form.values);
20+
}
21+
1622
// Use the standard html form element, which exposes the onSubmit event.
1723
return (
18-
<form
19-
onSubmit={form.handleSubmit(() => {
20-
// The form.handleSubmit validates the form before calling your callback
21-
console.log("submit", form.values);
22-
})}
23-
>
24+
<form onSubmit={form.handleSubmit(submit)}>
2425
{/* Make sure to add type="submit" */}
2526
<button type="submit">Submit!</button>
2627
</form>
@@ -29,17 +30,18 @@ function MyForm() {
2930

3031
function MyForm2() {
3132
const form = useForm({ email: "", password: "" });
33+
34+
async function submit() {
35+
// Implement your submit logic here...
36+
console.log("submitting", form.values);
37+
// Fake fetch, by waiting for 500ms
38+
await new Promise((res) => setTimeout(res, 500));
39+
// Optional: set new default values
40+
form.setDefaultValues(form.values);
41+
}
42+
3243
return (
33-
<form
34-
onSubmit={form.handleSubmit(async (ev) => {
35-
// Implement your submit logic here...
36-
console.log("submitting", form.values);
37-
// Fake fetch, by waiting for 500ms
38-
await new Promise((res) => setTimeout(res, 500));
39-
// Optional: set new default values
40-
form.setDefaultValues(form.values);
41-
})}
42-
>
44+
<form onSubmit={form.handleSubmit(submit)}>
4345
{/* Make sure to pass the form prop! */}
4446
<FormInput form={form} name="email" type="text" />
4547
<FormInput form={form} name="password" type="password" />

0 commit comments

Comments
 (0)