Created
November 1, 2022 11:26
-
-
Save ilyaagarkov/558f80ad6ea155d5fbd74d70f095f883 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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