Skip to content

Instantly share code, notes, and snippets.

@ilyaagarkov
Created November 1, 2022 11:26
Show Gist options
  • Save ilyaagarkov/558f80ad6ea155d5fbd74d70f095f883 to your computer and use it in GitHub Desktop.
Save ilyaagarkov/558f80ad6ea155d5fbd74d70f095f883 to your computer and use it in GitHub Desktop.
import { createContext, ReactNode, useContext } from "react";
import {
ControllerInjectedResult,
Form as FormType,
useForm,
useFieldArray,
} from "effector-react-form";
import { FieldArray, ResultUseFieldArray } from "effector-react-form/types/ts";
export const FormContext = createContext<any>(null);
export const FieldArrayContext = createContext<FieldArray | null>(null);
export function Form(props: {
form: FormType;
children: ReactNode;
className?: string;
fieldArray?: FieldArray;
resetUnmount?: boolean;
}): JSX.Element {
const form = useForm({ form: props.form, resetUnmount: props.resetUnmount });
return (
<FormContext.Provider value={form}>
<FieldArrayContext.Provider value={props.fieldArray ?? null}>
<form
className={props.className}
onSubmit={(e) => {
form.handleSubmit(e);
e.stopPropagation();
}}
>
{props.children}
</form>
</FieldArrayContext.Provider>
</FormContext.Provider>
);
}
const NestedContext = createContext<string | null>(null);
interface ListFieldProps {
name: string;
children(params: ResultUseFieldArray): ReactNode;
}
export function ListField(props: ListFieldProps): JSX.Element {
const fieldArray = useContext(FieldArrayContext);
if (fieldArray === null) {
throw Error(
`ListField with name ${props.name} can't find FieldArrayContext value`
);
}
const fieldArrayParams = useFieldArray({
name: props.name,
fieldArray,
});
return (
<NestedContext.Provider value={props.name}>
{props.children({
...fieldArrayParams,
map: (cb) =>
fieldArrayParams.map((params) => (
<NestedFields name={params.formItemName}>{cb(params)}</NestedFields>
)),
})}
</NestedContext.Provider>
);
}
export function NestedFields(props: {
name: string;
children: ReactNode;
}): JSX.Element {
return (
<NestedContext.Provider value={props.name}>
{props.children}
</NestedContext.Provider>
);
}
export function useNestedName(name: string): string {
const nested = useContext(NestedContext);
return nested ? `${nested}.${name}` : name;
}
export function useField(props: { name: string }): ControllerInjectedResult {
const form = useContext(FormContext);
const name = useNestedName(props.name);
return form.controller({ name: name })();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment