import * as React from 'react';
import { ReactNode } from 'react';
import { useFormContext, FieldValues } from 'react-hook-form';
import get from 'lodash/get.js';
import { useFormValues } from './useFormValues';
import { useWrappedSource } from '../core';
/**
* Get the current (edited) value of the record from the form and pass it
* to a child function
*
* @example
*
* const PostEdit = () => (
*
* >
*
*
* {({ formData }) => formData.hasEmail &&
*
* }
*
*
*
* );
*
* @example
*
* const OrderEdit = () => (
*
*
*
* >
* {({ formData }) =>
*
* }
*
*
*
* );
*/
export const FormDataConsumer = <
TFieldValues extends FieldValues = FieldValues,
>(
props: ConnectedProps
) => {
const form = useFormContext();
const {
formState: {
// Don't know exactly why, but this is needed for the form values to be updated
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isDirty,
},
} = form;
const formData = useFormValues();
return (
formData={formData} {...props} />
);
};
export const FormDataConsumerView = <
TFieldValues extends FieldValues = FieldValues,
>(
props: Props
) => {
const { children, formData, source } = props;
let result;
const finalSource = useWrappedSource(source || '');
// Passes an empty string here as we don't have the children sources and we just want to know if we are in an iterator
const arraySource = getArraySource(finalSource);
// If we have an index, we are in an iterator like component (such as the SimpleFormIterator)
if (arraySource) {
const scopedFormData = get(formData, arraySource);
result = children({ formData, scopedFormData });
} else {
result = children({ formData });
}
return result === undefined ? null : result;
};
const getArraySource = (source: string) =>
source.lastIndexOf('.') > 0 && ArraySourceRegex.test(source)
? source
: undefined;
const ArraySourceRegex = /\.\d+$/;
export interface FormDataConsumerRenderParams<
TFieldValues extends FieldValues = FieldValues,
TScopedFieldValues extends FieldValues = TFieldValues,
> {
formData: TFieldValues;
scopedFormData?: TScopedFieldValues;
}
export type FormDataConsumerRender<
TFieldValues extends FieldValues = FieldValues,
> = (params: FormDataConsumerRenderParams) => ReactNode;
interface ConnectedProps {
children: FormDataConsumerRender;
/**
* @deprecated This prop will be removed in a future major release.
*/
form?: string;
/**
* @deprecated This prop will be removed in a future major release.
*/
record?: any;
/**
* @deprecated This prop will be removed in a future major release.
*/
source?: string;
/**
* @deprecated This prop will be removed in a future major release.
*/
[key: string]: any;
}
interface Props extends ConnectedProps {
formData: TFieldValues;
/**
* @deprecated This prop will be removed in a future major release.
*/
index?: number;
}