Skip to content

Commit

Permalink
Fix RecordContext and UseRecordContext
Browse files Browse the repository at this point in the history
  • Loading branch information
djhi committed Mar 15, 2021
1 parent 58e00dc commit 5c4ede0
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 32 deletions.
62 changes: 36 additions & 26 deletions packages/ra-core/src/controller/RecordContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import { createContext, ReactNode, useContext, useMemo } from 'react';
import pick from 'lodash/pick';
import { createContext, ReactNode, useContext } from 'react';
import { Record } from '../types';

/**
Expand All @@ -13,7 +12,7 @@ import { Record } from '../types';
* import { useEditController, EditContext } from 'ra-core';
*
* const Edit = props => {
* const { record }= useEditController(props);
* const { record } = useEditController(props);
* return (
* <RecordContextProvider value={record}>
* ...
Expand All @@ -25,22 +24,21 @@ export const RecordContext = createContext<Record | Omit<Record, 'id'>>(
undefined
);

export const RecordContextProvider = ({
export const RecordContextProvider = <
RecordType extends Record | Omit<Record, 'id'> = Record
>({
children,
value,
}: RecordContextOptions) => (
}: RecordContextOptions<RecordType>) => (
<RecordContext.Provider value={value}>{children}</RecordContext.Provider>
);

RecordContext.displayName = 'RecordContext';

export const usePickRecordContext = <
RecordType extends Record | Omit<Record, 'id'> = Record
>(
context: RecordType
) => {
const value = useMemo(() => pick(context, ['record']), [context.record]); // eslint-disable-line
return value;
};
export interface RecordContextOptions<RecordType> {
children: ReactNode;
value?: RecordType;
}

/**
* Hook to read the record from a RecordContext.
Expand All @@ -49,30 +47,42 @@ export const usePickRecordContext = <
* (e.g. as a descendent of <Edit> or <EditBase>) or within a <ShowContextProvider>
* (e.g. as a descendent of <Show> or <ShowBase>)
*
* @returns {Record} The record context
* @example // basic usage
*
* import { useRecordContext } from 'ra-core';
*
* const TitleField = () => {
* const record = useRecordContext();
* return <span>{record && record.title}</span>;
* };
*
* @example // allow record override via props
*
* import { useRecordContext } from 'ra-core';
*
* const TitleField = (props) => {
* const record = useRecordContext(props);
* return <span>{record && record.title}</span>;
* };
* render(<TextField record={record} />);
*
* @returns {Record} A record object
*/
export const useRecordContext = <
RecordType extends Record | Omit<Record, 'id'> = Record
>(
props: RecordType
props: UseRecordContextParams<RecordType>
): RecordType => {
// Can't find a way to specify the RecordType when CreateContext is declared
// @ts-ignore
const context = useContext<RecordType>(RecordContext);

if (!context) {
// As the record could very well be undefined because not yet loaded
// We don't display a deprecation warning yet
// @deprecated - to be removed in 4.0
return props;
}

return context;
return (props && props.record) || context;
};

export interface RecordContextOptions<
export interface UseRecordContextParams<
RecordType extends Record | Omit<Record, 'id'> = Record
> {
children: ReactNode;
value?: RecordType;
record?: RecordType;
[key: string]: any;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as React from 'react';
import { ReactElement } from 'react';
import { RecordContextProvider, usePickRecordContext } from '../RecordContext';
import { RecordContextProvider } from '../RecordContext';
import { CreateContext } from './CreateContext';
import { CreateControllerProps } from './useCreateController';
import { SaveContextProvider, usePickSaveContext } from './SaveContext';
import { Record } from '../../types';

/**
* Create a Create Context.
Expand Down Expand Up @@ -37,7 +38,9 @@ export const CreateContextProvider = ({
}) => (
<CreateContext.Provider value={value}>
<SaveContextProvider value={usePickSaveContext(value)}>
<RecordContextProvider value={usePickRecordContext(value)}>
<RecordContextProvider<Partial<Record>>
value={value && value.record}
>
{children}
</RecordContextProvider>
</SaveContextProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as React from 'react';
import { ReactElement } from 'react';
import { RecordContextProvider, usePickRecordContext } from '../RecordContext';
import { RecordContextProvider } from '../RecordContext';
import { EditContext } from './EditContext';
import { EditControllerProps } from './useEditController';
import { SaveContextProvider, usePickSaveContext } from './SaveContext';
import { Record } from '../../types';

/**
* Create an Edit Context.
Expand Down Expand Up @@ -37,7 +38,9 @@ export const EditContextProvider = ({
}) => (
<EditContext.Provider value={value}>
<SaveContextProvider value={usePickSaveContext(value)}>
<RecordContextProvider value={usePickRecordContext(value)}>
<RecordContextProvider<Partial<Record>>
value={value && value.record}
>
{children}
</RecordContextProvider>
</SaveContextProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { ReactElement } from 'react';
import { RecordContextProvider, usePickRecordContext } from '../RecordContext';
import { Record } from '../../types';
import { RecordContextProvider } from '../RecordContext';
import { ShowContext } from './ShowContext';
import { ShowControllerProps } from './useShowController';

Expand Down Expand Up @@ -33,7 +34,7 @@ export const ShowContextProvider = ({
value: ShowControllerProps;
}) => (
<ShowContext.Provider value={value}>
<RecordContextProvider value={usePickRecordContext(value)}>
<RecordContextProvider<Partial<Record>> value={value && value.record}>
{children}
</RecordContextProvider>
</ShowContext.Provider>
Expand Down

0 comments on commit 5c4ede0

Please sign in to comment.