import React, { ReactNode, useMemo } from 'react'; import { useReferenceOneFieldController, UseReferenceOneFieldControllerParams, } from './useReferenceOneFieldController'; import { useRecordContext, RecordContextProvider } from '../record'; import { ResourceContextProvider } from '../../core'; import { ReferenceFieldContextProvider } from './ReferenceFieldContext'; import { useGetPathForRecord } from '../../routing'; import type { UseReferenceFieldControllerResult } from './useReferenceFieldController'; import type { RaRecord } from '../../types'; import type { LinkToType } from '../../routing'; import { UseReferenceResult } from '../useReference'; /** * Render the related record in a one-to-one relationship * * Expects a single field as child * * @example // display the bio of the current author * * * */ export const ReferenceOneFieldBase = < RecordType extends RaRecord = RaRecord, ReferenceRecordType extends RaRecord = RaRecord, >( props: ReferenceOneFieldBaseProps ) => { const { children, render, record, reference, source = 'id', target, empty, error, loading, sort, filter, link, offline, queryOptions, } = props; const controllerProps = useReferenceOneFieldController< RecordType, ReferenceRecordType >({ record, reference, source, target, sort, filter, queryOptions, }); const path = useGetPathForRecord({ record: controllerProps.referenceRecord, resource: reference, link, }); const context = useMemo( () => ({ ...controllerProps, link: path, }), [controllerProps, path] ); if (!render && !children) { throw new Error( " requires either a 'render' prop or 'children' prop" ); } const recordFromContext = useRecordContext(props); const { error: controllerError, isPending, isPaused, referenceRecord, } = controllerProps; const shouldRenderLoading = !isPaused && isPending && loading !== false && loading !== undefined; const shouldRenderOffline = isPaused && isPending && offline !== false && offline !== undefined; const shouldRenderError = !!controllerError && error !== false && error !== undefined; const shouldRenderEmpty = (!recordFromContext || (!isPaused && referenceRecord == null && !controllerError && !isPending)) && empty !== false && empty !== undefined; return ( {shouldRenderLoading ? loading : shouldRenderOffline ? offline : shouldRenderError ? error : shouldRenderEmpty ? empty : render ? render(controllerProps) : children} ); }; export interface ReferenceOneFieldBaseProps< RecordType extends RaRecord = RaRecord, ReferenceRecordType extends RaRecord = RaRecord, > extends UseReferenceOneFieldControllerParams< RecordType, ReferenceRecordType > { children?: ReactNode; loading?: ReactNode; error?: ReactNode; empty?: ReactNode; offline?: ReactNode; render?: (props: UseReferenceResult) => ReactNode; link?: LinkToType; resource?: string; }