Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #296 from wellyshen/feature/change-dirty-fields-to…
Browse files Browse the repository at this point in the history
…-dirty

Feat(useForm): rename "dirtyFields" state and option to "dirty"
  • Loading branch information
wellyshen authored Jan 2, 2021
2 parents 92289f1 + 4399c18 commit 19b47df
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/rotten-feet-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-cool-form": patch
---

Feat(useForm): rename `dirtyFields` state and option to `dirty`
8 changes: 4 additions & 4 deletions docs/api-reference/use-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ An `object` with the following options:

`Record<string, any>`

Default field values of the form. In most case (especially working with TypeScript), we should use it to initialize a field's value and use the [defaultValue/defaultChecked](https://reactjs.org/docs/uncontrolled-components.html#default-values) attribute for the case of [conditional fields](../examples/conditional-fields). The `defaultValues` also used to compare against the current values to calculate `isDirty` and `dirtyFields`.
Default field values of the form. In most case (especially working with TypeScript), we should use it to initialize a field's value and use the [defaultValue/defaultChecked](https://reactjs.org/docs/uncontrolled-components.html#default-values) attribute for the case of [conditional fields](../examples/conditional-fields). The `defaultValues` also used to compare against the current values to calculate `isDirty` and `dirty`.

> 💡 The `defaultValues` is cached **at the first render** within the custom hook. If you want to reset it or [lazily set it](../examples/lazy-default-values), you can use the [reset](#reset) method.
Expand All @@ -33,7 +33,7 @@ Tell React Cool Form to ignore field(s) by passing in the `name` of the field. Y

`boolean`

By default, React Cool Form auto removes the related state (i.e. `values`, `errors`, `touched`, `dirtyFields`) of an unmounted field for us. However, we can set the `shouldRemoveField` to `false` to maintain the state. Check the [conditional fields](../examples/conditional-fields) example to learn more. Default is `true`.
By default, React Cool Form auto removes the related state (i.e. `values`, `errors`, `touched`, `dirty`) of an unmounted field for us. However, we can set the `shouldRemoveField` to `false` to maintain the state. Check the [conditional fields](../examples/conditional-fields) example to learn more. Default is `true`.

> 💡 If the field isn't a form input element (i.e. [input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input), [select](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select), and [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)) or [controller](#controller)'s target. We need to clear the related state by ourselves via `set`-related methods.
Expand Down Expand Up @@ -219,8 +219,8 @@ setValues(
shouldValidate: true, // (Default = "validateOnChange" option) Triggers form validation
touched: ["firstName"], // Sets fields as touched by passing their names
// touched: (allFieldNames) => allFieldNames, // A reverse way to set touched fields
dirtyFields: ["firstName"], // Sets fields as dirty by passing their names
// dirtyFields: (allFieldNames) => allFieldNames, // A reverse way to set dirty fields
dirty: ["firstName"], // Sets fields as dirty by passing their names
// dirty: (allFieldNames) => allFieldNames, // A reverse way to set dirty fields
}
);

Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started/form-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Form state is an `object` containing the following values:
| errors | `object` | The current validation errors. [The shape will (should) match the shape of the form's values](./validation-guide#how-to-run). |
| touched | `object` | An object containing all the fields the user has touched/visited. |
| isDirty | `boolean` | Returns `true` if the user modifies any of the fields. `false` otherwise. |
| dirtyFields | `object` | An object containing all the fields the user has modified. |
| dirty | `object` | An object containing all the fields the user has modified. |
| isValidating | `boolean` | Returns `true` if the form is currently being validated. `false` otherwise. |
| isValid | `boolean` | Returns `true` if the form doesn't have any errors (i.e. the `errors` object is empty). `false` otherwise. |
| isSubmitting | `boolean` | Returns `true` if the form is currently being submitted. `false` if otherwise. |
Expand Down Expand Up @@ -93,7 +93,7 @@ const errors = getState("errors");
const fooError = getState("errors.foo");

// 🙆🏻‍♀️ It's OK, they are triggered less frequently
const [touched, dirtyFields] = getState(["touched", "dirtyFields"]);
const [touched, dirty] = getState(["touched", "dirty"]);
```

### Reading the State
Expand Down
30 changes: 15 additions & 15 deletions src/hooks/__tests__/useState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("useState", () => {
values: { name: "Welly" },
touched: {},
errors: {},
dirtyFields: {},
dirty: {},
isDirty: false,
isValidating: false,
isValid: true,
Expand All @@ -43,7 +43,7 @@ describe("useState", () => {
touched: { name: true },
errors: { name: "Required" },
isDirty: true,
dirtyFields: { name: true },
dirty: { name: true },
isValid: false,
submitCount: 1,
};
Expand All @@ -66,7 +66,7 @@ describe("useState", () => {
setStateRef("values.name", name);
setStateRef("touched.name", true);
setStateRef("errors.name", error);
setStateRef("dirtyFields.name", true);
setStateRef("dirty.name", true);
setStateRef("isValidating", isValidating);
setStateRef("isSubmitting", isSubmitting);
setStateRef("isSubmitted", isSubmitted);
Expand All @@ -76,7 +76,7 @@ describe("useState", () => {
touched: { name: true },
errors: { name: error },
isDirty: true,
dirtyFields: { name: true },
dirty: { name: true },
isValidating,
isValid: false,
isSubmitting,
Expand Down Expand Up @@ -105,9 +105,9 @@ describe("useState", () => {
setStateRef("errors.name", error);
expect(forceUpdate).toHaveBeenCalledTimes(4);

setUsedStateRef("dirtyFields.name");
setStateRef("dirtyFields.name", true);
setStateRef("dirtyFields.name", true);
setUsedStateRef("dirty.name");
setStateRef("dirty.name", true);
setStateRef("dirty.name", true);
expect(forceUpdate).toHaveBeenCalledTimes(5);

const isValidating = true;
Expand All @@ -133,7 +133,7 @@ describe("useState", () => {
touched: { name: true },
errors: { name: error },
isDirty: true,
dirtyFields: { name: true },
dirty: { name: true },
isValidating,
isValid: false,
isSubmitting,
Expand All @@ -145,7 +145,7 @@ describe("useState", () => {
it("should set state.isValid and state.isDirty without re-render", () => {
const { setStateRef } = renderHelper();
setStateRef("errors", { name: "Required" });
setStateRef("dirtyFields", { name: true });
setStateRef("dirty", { name: true });
expect(forceUpdate).not.toHaveBeenCalled();
});

Expand All @@ -158,8 +158,8 @@ describe("useState", () => {
expect(forceUpdate).toHaveBeenCalledTimes(1);

setUsedStateRef("isDirty");
setStateRef("dirtyFields", { name: true });
setStateRef("dirtyFields", { name: true });
setStateRef("dirty", { name: true });
setStateRef("dirty", { name: true });
expect(forceUpdate).toHaveBeenCalledTimes(2);
});

Expand All @@ -178,8 +178,8 @@ describe("useState", () => {
setStateRef("errors.name", "Required");
expect(forceUpdate).toHaveBeenCalledTimes(3);

setUsedStateRef("dirtyFields");
setStateRef("dirtyFields.name", true);
setUsedStateRef("dirty");
setStateRef("dirty.name", true);
expect(forceUpdate).toHaveBeenCalledTimes(4);
});

Expand All @@ -198,8 +198,8 @@ describe("useState", () => {
setStateRef("errors", { name: "Required" });
expect(forceUpdate).toHaveBeenCalledTimes(3);

setUsedStateRef("dirtyFields.name");
setStateRef("dirtyFields", { name: true });
setUsedStateRef("dirty.name");
setStateRef("dirty", { name: true });
expect(forceUpdate).toHaveBeenCalledTimes(4);
});

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ export default <V>(
const state = set(stateRef.current, path, value, true);
const {
errors,
dirtyFields,
dirty,
isDirty: prevIsDirty,
isValid: prevIsValid,
} = state;
let { submitCount: prevSubmitCount } = state;
const isDirty =
key === "dirtyFields" ? getIsDirty(dirtyFields) : prevIsDirty;
key === "dirty" ? getIsDirty(dirty) : prevIsDirty;
const isValid = key === "errors" ? isEmptyObject(errors) : prevIsValid;
const submitCount =
key === "isSubmitting" && value
Expand Down
4 changes: 2 additions & 2 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface FormState<V> {
touched: DeepProps<V, boolean>;
errors: FormErrors<V>;
isDirty: boolean;
dirtyFields: DeepProps<V, boolean>;
dirty: DeepProps<V, boolean>;
isValidating: boolean;
isValid: boolean;
isSubmitting: boolean;
Expand Down Expand Up @@ -159,7 +159,7 @@ export interface SetValues<V> {
options?: {
shouldValidate?: boolean;
touched?: string[] | FieldNamesFn;
dirtyFields?: string[] | FieldNamesFn;
dirty?: string[] | FieldNamesFn;
}
): void;
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/react-cool-form.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ declare module "react-cool-form" {
options?: {
shouldValidate?: boolean;
touched?: string[] | FieldNamesFn;
dirtyFields?: string[] | FieldNamesFn;
dirty?: string[] | FieldNamesFn;
}
): void;
}
Expand Down Expand Up @@ -104,7 +104,7 @@ declare module "react-cool-form" {
touched: DeepProps<V, boolean>;
errors: FormErrors<V>;
isDirty: boolean;
dirtyFields: DeepProps<V, boolean>;
dirty: DeepProps<V, boolean>;
isValidating: boolean;
isValid: boolean;
isSubmitting: boolean;
Expand Down
26 changes: 13 additions & 13 deletions src/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export default <V extends FormValues = FormValues>({
touched: {},
errors: {},
isDirty: false,
dirtyFields: {},
dirty: {},
isValidating: false,
isValid: true,
isSubmitting: false,
Expand Down Expand Up @@ -545,12 +545,12 @@ export default <V extends FormValues = FormValues>({
get(stateRef.current.values, name) !==
get(initialStateRef.current.values, name)
) {
setStateRef(`dirtyFields.${name}`, true);
setStateRef(`dirty.${name}`, true);
} else {
handleUnset(
"dirtyFields",
`dirtyFields.${name}`,
stateRef.current.dirtyFields,
"dirty",
`dirty.${name}`,
stateRef.current.dirty,
name
);
}
Expand Down Expand Up @@ -582,7 +582,7 @@ export default <V extends FormValues = FormValues>({
{
shouldValidate = validateOnChange,
touched = [],
dirtyFields = [],
dirty = [],
} = {}
) => {
values = isFunction(values) ? values(stateRef.current.values) : values;
Expand All @@ -600,12 +600,12 @@ export default <V extends FormValues = FormValues>({
: touched
)
);
if (dirtyFields.length)
if (dirty.length)
setStateRef(
"dirtyFields",
"dirty",
setTrueValues(
stateRef.current.dirtyFields,
isFunction(dirtyFields) ? dirtyFields(getFieldNames()) : dirtyFields
stateRef.current.dirty,
isFunction(dirty) ? dirty(getFieldNames()) : dirty
)
);
if (shouldValidate) validateFormWithLowPriority();
Expand Down Expand Up @@ -894,9 +894,9 @@ export default <V extends FormValues = FormValues>({
name
);
handleUnset(
"dirtyFields",
`dirtyFields.${name}`,
stateRef.current.dirtyFields,
"dirty",
`dirty.${name}`,
stateRef.current.dirty,
name
);
handleUnset(
Expand Down

0 comments on commit 19b47df

Please sign in to comment.