diff --git a/.changeset/six-cherries-boil.md b/.changeset/six-cherries-boil.md
new file mode 100644
index 00000000..73b05f7d
--- /dev/null
+++ b/.changeset/six-cherries-boil.md
@@ -0,0 +1,5 @@
+---
+"react-cool-form": patch
+---
+
+fix(useFieldArray): nested field array not working
diff --git a/app/src/Playground/index.tsx b/app/src/Playground/index.tsx
index ce93eb03..53d04332 100644
--- a/app/src/Playground/index.tsx
+++ b/app/src/Playground/index.tsx
@@ -1,23 +1,92 @@
/* eslint-disable no-console */
-import { useForm } from "react-cool-form";
+import { useForm, useFieldArray } from "react-cool-form";
export default () => {
- const { form, runValidation } = useForm({
- // validate: () => ({ foo: "Required" }),
- focusOnError: ["foo"],
+ const { form } = useForm({
+ defaultValues: {
+ foo: [
+ {
+ name: "Iron Man",
+ arr: [{ name: "iron arr.0" }, { name: "iron arr.1" }],
+ },
+ ],
+ },
+ onSubmit: (values) => alert(JSON.stringify(values, undefined, 2)),
});
+ const [fields, { push, insert, remove }] = useFieldArray("foo");
return (
- <>
-
-
- >
+
);
};
+
+function Arr({ field }: any) {
+ const [fields, { push }] = useFieldArray(`${field}.arr`);
+
+ return (
+
+ {fields.map((fieldName) => (
+
+ ))}
+
+
+ );
+}
diff --git a/src/types/index.ts b/src/types/index.ts
index 14390f9f..e122f27f 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -92,7 +92,7 @@ export type Fields = Map<
export type Parsers = ObjMap>;
-export type FieldArray = ObjMap<{ fields: ObjMap; reset: () => void }>;
+export type FieldArray = ObjMap<{ fields: ObjMap; update: () => void }>;
interface EventOptions {
removeField: RemoveField;
diff --git a/src/useFieldArray.ts b/src/useFieldArray.ts
index 6b2e3000..1cf95984 100644
--- a/src/useFieldArray.ts
+++ b/src/useFieldArray.ts
@@ -66,11 +66,13 @@ export default (
const [fields, setFields] = useState(getFields(true));
const updateFields = useCallback(() => {
- setFields(getFields());
- setNodesOrValues(getState("values"), {
- shouldSetValues: false,
- fields: Object.keys(fieldArrayRef.current[name].fields),
- });
+ if (fieldArrayRef.current[name]) {
+ setFields(getFields());
+ setNodesOrValues(getState("values"), {
+ shouldSetValues: false,
+ fields: Object.keys(fieldArrayRef.current[name].fields),
+ });
+ }
}, [fieldArrayRef, getFields, getState, name, setNodesOrValues]);
useEffect(() => {
@@ -83,14 +85,14 @@ export default (
}
return () => {
- if (shouldRemoveField(name)) removeField(name);
+ if (shouldRemoveField(name)) removeField(name, ["defaultValue"]);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (!fieldArrayRef.current[name])
fieldArrayRef.current[name] = {
- reset: updateFields,
+ update: updateFields,
fields: {},
};
if (validate) fieldValidatorsRef.current[name] = validate;
@@ -106,8 +108,8 @@ export default (
let state = getState();
(["values", "touched", "errors", "dirty"] as Keys[]).forEach((key) => {
- const value = state[key][name];
- const fieldsLength = state.values[name]?.length;
+ const value = get(state[key], name);
+ const fieldsLength = get(state.values, name)?.length;
if (
key === "values" ||
@@ -117,15 +119,12 @@ export default (
)
state = set(
state,
- key,
- {
- ...state[key],
- [name]: handler(
- Array.isArray(value) ? [...value] : [],
- key,
- fieldsLength ? fieldsLength - 1 : 0
- ),
- },
+ `${key}.${name}`,
+ handler(
+ Array.isArray(value) ? [...value] : [],
+ key,
+ fieldsLength ? fieldsLength - 1 : 0
+ ),
true
);
});
diff --git a/src/useForm.ts b/src/useForm.ts
index b003ee65..9a3394e5 100644
--- a/src/useForm.ts
+++ b/src/useForm.ts
@@ -704,7 +704,7 @@ export default ({
setNodeValue(name, value);
isFieldArray(fieldArrayRef.current, name, (key) =>
- fieldArrayRef.current[key].reset()
+ fieldArrayRef.current[key].update()
);
if (shouldTouched) setTouched(name, true, { shouldValidate: false });
@@ -774,7 +774,7 @@ export default ({
setStateRef("", state);
onResetRef.current(state.values, getOptions(), e);
- Object.values(fieldArrayRef.current).forEach((field) => field.reset());
+ Object.values(fieldArrayRef.current).forEach((field) => field.update());
},
[getOptions, onResetRef, setNodesOrValues, setStateRef, stateRef]
);