Skip to content

Commit

Permalink
Merge pull request #5730 from marmelab/fix-Create-Edit-Show-cannot-be…
Browse files Browse the repository at this point in the history
…-used-outside-ResourceContextProvider

Fix Create, Edit and Show cannot be used outside of a ResourceContextProvider
  • Loading branch information
djhi committed Jan 4, 2021
2 parents 549af03 + dbe1e42 commit fe6f771
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 24 deletions.
50 changes: 30 additions & 20 deletions packages/ra-core/src/core/useResourceContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,42 @@ import { ResourceContext, ResourceContextValue } from './ResourceContext';
* Hook to read the resource from the ResourceContext.
*
* Must be used within a <ResourceContextProvider> (e.g. as a descendent of <Resource>
* or any reference related components).
* or any reference related components), or called with a resource prop.
*
* @returns {ResourceContextValue} The resource
* @example
*
* const ResourceName = (props) => {
* const { resource } = useResourceContext(props);
* const resourceName = translate(`resources.${resource}.name`, {
* smart_count: 1,
* _: inflection.humanize(inflection.singularize(resource)),
* });
* return <>{resourceName}</>;
* }
*
* // use it in a resource context
* const MyComponent = () => (
* <ResourceContextProvider value="posts">
* <ResourceName />
* ...
* </ResourceContextProvider>
* );
*
* // override resource via props
* const MyComponent = () => (
* <>
* <ResourceName resource="posts"/>
* ...
* </>
* );
*
* @returns {ResourceContextValue} The resource name, e.g. 'posts'
*/
export const useResourceContext = <
ResourceInformationsType extends Partial<{ resource: string }>
>(
props?: ResourceInformationsType
): ResourceContextValue => {
const context = useContext(ResourceContext);

if (!context) {
/**
* The element isn't inside a <ResourceContextProvider>
*
* @deprecated - to be removed in 4.0
*/
if (process.env.NODE_ENV !== 'production') {
// Restore this message when ResourceContext is actually used
// console.warn(
// "Any react-admin components must be used inside a <ResourceContextProvider>. Relying on props rather than context to get the resource data is deprecated and won't be supported in the next major version of react-admin."
// );
}
// Ignored because resource is often optional (as it is injected) in components which passes the props to this hook
return props && props.resource;
}

return context;
return props.resource || context;
};
13 changes: 11 additions & 2 deletions packages/ra-ui-materialui/src/detail/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReactElement } from 'react';
import PropTypes from 'prop-types';
import {
CreateContextProvider,
ResourceContextProvider,
useCheckMinimumRequiredProps,
useCreateController,
} from 'ra-core';
Expand Down Expand Up @@ -58,11 +59,19 @@ export const Create = (
): ReactElement => {
useCheckMinimumRequiredProps('Create', ['children'], props);
const controllerProps = useCreateController(props);
return (
const body = (
<CreateContextProvider value={controllerProps}>
<CreateView {...props} {...controllerProps} />
</CreateContextProvider>
);
return props.resource ? (
// support resource override via props
<ResourceContextProvider value={props.resource}>
{body}
</ResourceContextProvider>
) : (
body
);
};

Create.propTypes = {
Expand All @@ -74,7 +83,7 @@ Create.propTypes = {
hasCreate: PropTypes.bool,
hasEdit: PropTypes.bool,
hasShow: PropTypes.bool,
resource: PropTypes.string.isRequired,
resource: PropTypes.string,
title: PropTypes.node,
record: PropTypes.object,
hasList: PropTypes.bool,
Expand Down
11 changes: 10 additions & 1 deletion packages/ra-ui-materialui/src/detail/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReactElement } from 'react';
import PropTypes from 'prop-types';
import {
EditContextProvider,
ResourceContextProvider,
useCheckMinimumRequiredProps,
useEditController,
} from 'ra-core';
Expand Down Expand Up @@ -59,11 +60,19 @@ export const Edit = (
): ReactElement => {
useCheckMinimumRequiredProps('Edit', ['children'], props);
const controllerProps = useEditController(props);
return (
const body = (
<EditContextProvider value={controllerProps}>
<EditView {...props} {...controllerProps} />
</EditContextProvider>
);
return props.resource ? (
// support resource override via props
<ResourceContextProvider value={props.resource}>
{body}
</ResourceContextProvider>
) : (
body
);
};

Edit.propTypes = {
Expand Down
11 changes: 10 additions & 1 deletion packages/ra-ui-materialui/src/detail/Show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReactElement } from 'react';
import PropTypes from 'prop-types';
import {
ShowContextProvider,
ResourceContextProvider,
useCheckMinimumRequiredProps,
useShowController,
} from 'ra-core';
Expand Down Expand Up @@ -58,11 +59,19 @@ export const Show = (
): ReactElement => {
useCheckMinimumRequiredProps('Show', ['children'], props);
const controllerProps = useShowController(props);
return (
const body = (
<ShowContextProvider value={controllerProps}>
<ShowView {...props} {...controllerProps} />
</ShowContextProvider>
);
return props.resource ? (
// support resource override via props
<ResourceContextProvider value={props.resource}>
{body}
</ResourceContextProvider>
) : (
body
);
};

Show.propTypes = {
Expand Down

0 comments on commit fe6f771

Please sign in to comment.