Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move middlewares to dataProvider hooks #9855

Merged
merged 9 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/Upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,40 @@ The `data-generator-retail` package has been updated to provide types for all it

React-admin no longer supports ([deprecated React PropTypes](https://legacy.reactjs.org/blog/2017/04/07/react-v15.5.0.html#new-deprecation-warnings)). We encourage you to switch to TypeScript to type component props.

### Mutation Middlewares No Longer Receive The Mutation Options

Mutations middlewares no longer receive the mutation options:

```diff
import * as React from 'react';
import {
useRegisterMutationMiddleware,
CreateParams,
- MutateOptions,
CreateMutationFunction
} from 'react-admin';

const MyComponent = () => {
const createMiddleware = async (
resource: string,
params: CreateParams,
- options: MutateOptions,
next: CreateMutationFunction
) => {
// Do something before the mutation

// Call the next middleware
- await next(resource, params, options);
+ await next(resource, params);

// Do something after the mutation
}
const memoizedMiddleWare = React.useCallback(createMiddleware, []);
useRegisterMutationMiddleware(memoizedMiddleWare);
// ...
}
```

## Upgrading to v4

If you are on react-admin v3, follow the [Upgrading to v4](https://marmelab.com/react-admin/doc/4.16/Upgrade.html) guide before upgrading to v5.
11 changes: 4 additions & 7 deletions docs/useRegisterMutationMiddleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,19 @@ import * as React from 'react';
import {
useRegisterMutationMiddleware,
CreateParams,
MutateOptions,
CreateMutationFunction
} from 'react-admin';

const MyComponent = () => {
const createMiddleware = async (
resource: string,
params: CreateParams,
options: MutateOptions,
next: CreateMutationFunction
) => {
// Do something before the mutation

// Call the next middleware
await next(resource, params, options);
await next(resource, params);

// Do something after the mutation
}
Expand All @@ -65,11 +63,11 @@ React-admin will wrap each call to the `dataProvider.create()` mutation with the
A middleware function must have the following signature:

```jsx
const middlware = async (resource, params, options, next) => {
const middlware = async (resource, params, next) => {
// Do something before the mutation

// Call the next middleware
await next(resource, params, options);
await next(resource, params);

// Do something after the mutation
}
Expand Down Expand Up @@ -97,13 +95,12 @@ const ThumbnailInput = () => {
const middleware = useCallback(async (
resource,
params,
options,
next
) => {
const b64 = await convertFileToBase64(params.data.thumbnail);
// Update the parameters that will be sent to the dataProvider call
const newParams = { ...params, data: { ...data, thumbnail: b64 } };
await next(resource, newParams, options);
await next(resource, newParams);
}, []);
useRegisterMutationMiddleware(middleware);

Expand Down
3 changes: 2 additions & 1 deletion packages/ra-core/src/controller/create/CreateController.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ReactNode } from 'react';
import {
useCreateController,
CreateControllerProps,
Expand All @@ -21,7 +22,7 @@ export const CreateController = ({
children,
...props
}: {
children: (params: CreateControllerResult) => JSX.Element;
children: (params: CreateControllerResult) => ReactNode;
} & CreateControllerProps) => {
const controllerProps = useCreateController(props);
return children(controllerProps);
Expand Down
24 changes: 10 additions & 14 deletions packages/ra-core/src/controller/create/useCreateController.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
useInput,
} from '../..';
import { CoreAdminContext } from '../../core';
import { testDataProvider, useCreate } from '../../dataProvider';
import { testDataProvider } from '../../dataProvider';
import { useNotificationContext } from '../../notification';
import {
Middleware,
Expand All @@ -35,9 +35,9 @@ describe('useCreateController', () => {
const location: Location = {
key: 'a_key',
pathname: '/foo',
search: undefined,
search: '',
state: undefined,
hash: undefined,
hash: '',
};

it('should return location state record when set', () => {
Expand Down Expand Up @@ -563,20 +563,17 @@ describe('useCreateController', () => {
const dataProvider = testDataProvider({
create,
});
const middleware: Middleware<ReturnType<typeof useCreate>[0]> = jest.fn(
(resource, params, options, next) => {
return next(
resource,
{ ...params, meta: { addedByMiddleware: true } },
options
);
const middleware: Middleware<DataProvider['create']> = jest.fn(
(resource, params, next) => {
return next(resource, {
...params,
meta: { addedByMiddleware: true },
});
}
);

const Child = () => {
useRegisterMutationMiddleware<ReturnType<typeof useCreate>[0]>(
middleware
);
useRegisterMutationMiddleware<DataProvider['create']>(middleware);
return null;
};
render(
Expand Down Expand Up @@ -616,7 +613,6 @@ describe('useCreateController', () => {
{
data: { foo: 'bar' },
},
expect.any(Object),
expect.any(Function)
);
});
Expand Down
8 changes: 4 additions & 4 deletions packages/ra-core/src/controller/create/useCreateController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const useCreateController = <
} = mutationOptions;
const {
registerMutationMiddleware,
getMutateWithMiddlewares,
mutateWithMiddlewares,
unregisterMutationMiddleware,
} = useMutationMiddlewares();

Expand Down Expand Up @@ -139,6 +139,7 @@ export const useCreateController = <
},
...otherMutationOptions,
returnPromise: true,
mutateWithMiddlewares,
});

const save = useCallback(
Expand All @@ -157,9 +158,8 @@ export const useCreateController = <
? transform(data)
: data
).then(async (data: Partial<RecordType>) => {
const mutate = getMutateWithMiddlewares(create);
try {
await mutate(
await create(
resource,
{ data, meta: metaFromSave ?? meta },
callTimeOptions
Expand All @@ -176,7 +176,7 @@ export const useCreateController = <
}
}
}),
[create, getMutateWithMiddlewares, meta, resource, transform]
[create, meta, resource, transform]
);

const getResourceLabel = useGetResourceLabel();
Expand Down
3 changes: 2 additions & 1 deletion packages/ra-core/src/controller/edit/EditController.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ReactNode } from 'react';
import {
useEditController,
EditControllerProps,
Expand All @@ -21,7 +22,7 @@ export const EditController = ({
children,
...props
}: {
children: (params: EditControllerResult) => JSX.Element;
children: (params: EditControllerResult) => ReactNode;
} & EditControllerProps) => {
const controllerProps = useEditController(props);
return children(controllerProps);
Expand Down
34 changes: 17 additions & 17 deletions packages/ra-core/src/controller/edit/useEditController.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import {
useEditController,
} from '..';
import { CoreAdminContext } from '../../core';
import { testDataProvider, useUpdate } from '../../dataProvider';
import { testDataProvider } from '../../dataProvider';
import undoableEventEmitter from '../../dataProvider/undoableEventEmitter';
import { Form, InputProps, useInput } from '../../form';
import { useNotificationContext } from '../../notification';
import { DataProvider } from '../../types';
import { Middleware, useRegisterMutationMiddleware } from '../saveContext';
import { EditController } from './EditController';
import { TestMemoryRouter } from '../../routing';
import { RedirectionSideEffect, TestMemoryRouter } from '../../routing';

describe('useEditController', () => {
const defaultProps = {
Expand Down Expand Up @@ -131,10 +131,14 @@ describe('useEditController', () => {
Promise.resolve({ data: { id: 12, title: 'hello' } })
);
const dataProvider = ({ getOne } as unknown) as DataProvider;
const Component = ({ redirect = undefined }) => (
const Component = ({
redirect = undefined,
}: {
redirect?: RedirectionSideEffect;
}) => (
<CoreAdminContext dataProvider={dataProvider}>
<EditController {...defaultProps} redirect={redirect}>
{({ redirect }) => <div>{redirect}</div>}
{({ redirect }) => <div>{redirect.toString()}</div>}
</EditController>
</CoreAdminContext>
);
Expand Down Expand Up @@ -224,7 +228,7 @@ describe('useEditController', () => {
<p>{record?.test}</p>
<button
aria-label="save"
onClick={() => save({ test: 'updated' })}
onClick={() => save!({ test: 'updated' })}
/>
</>
);
Expand Down Expand Up @@ -268,7 +272,7 @@ describe('useEditController', () => {
<p>{record?.test}</p>
<button
aria-label="save"
onClick={() => save({ test: 'updated' })}
onClick={() => save!({ test: 'updated' })}
/>
</>
);
Expand Down Expand Up @@ -1044,20 +1048,17 @@ describe('useEditController', () => {
getOne: () => Promise.resolve({ data: { id: 12 } }),
update,
});
const middleware: Middleware<ReturnType<typeof useUpdate>[0]> = jest.fn(
(resource, params, options, next) => {
return next(
resource,
{ ...params, meta: { addedByMiddleware: true } },
options
);
const middleware: Middleware<DataProvider['update']> = jest.fn(
(resource, params, next) => {
return next(resource, {
...params,
meta: { addedByMiddleware: true },
});
}
);

const Child = () => {
useRegisterMutationMiddleware<ReturnType<typeof useUpdate>[0]>(
middleware
);
useRegisterMutationMiddleware<DataProvider['update']>(middleware);
return null;
};
render(
Expand Down Expand Up @@ -1102,7 +1103,6 @@ describe('useEditController', () => {
id: 12,
data: { foo: 'bar' },
},
expect.any(Object),
expect.any(Function)
);
});
Expand Down
8 changes: 3 additions & 5 deletions packages/ra-core/src/controller/edit/useEditController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const useEditController = <
} = mutationOptions;
const {
registerMutationMiddleware,
getMutateWithMiddlewares,
mutateWithMiddlewares,
unregisterMutationMiddleware,
} = useMutationMiddlewares();
const {
Expand Down Expand Up @@ -192,6 +192,7 @@ export const useEditController = <
...otherMutationOptions,
mutationMode,
returnPromise: mutationMode === 'pessimistic',
mutateWithMiddlewares,
}
);

Expand All @@ -216,10 +217,8 @@ export const useEditController = <
})
: data
).then(async (data: Partial<RecordType>) => {
const mutate = getMutateWithMiddlewares(update);

try {
await mutate(
await update(
resource,
{
id,
Expand All @@ -239,7 +238,6 @@ export const useEditController = <
}),
[
id,
getMutateWithMiddlewares,
mutationMeta,
resource,
transform,
Expand Down
slax57 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ export const useMutationMiddlewares = <
[]
);

const getMutateWithMiddlewares = useCallback((fn: MutateFunc) => {
return (...args: Parameters<MutateFunc>): ReturnType<MutateFunc> => {
const mutateWithMiddlewares = useCallback(
(
fn: MutateFunc,
...args: Parameters<MutateFunc>
): ReturnType<MutateFunc> => {
let index = callbacks.current.length - 1;

// Called by middlewares to call the next middleware function
Expand All @@ -84,18 +87,19 @@ export const useMutationMiddlewares = <
}

return fn(...args);
};
}, []);
},
[]
);

const functions = useMemo<UseMutationMiddlewaresResult<MutateFunc>>(
() => ({
registerMutationMiddleware,
getMutateWithMiddlewares,
mutateWithMiddlewares,
unregisterMutationMiddleware,
}),
[
registerMutationMiddleware,
getMutateWithMiddlewares,
mutateWithMiddlewares,
unregisterMutationMiddleware,
]
);
Expand All @@ -107,9 +111,10 @@ export interface UseMutationMiddlewaresResult<
MutateFunc extends (...args: any[]) => any = (...args: any[]) => any
> {
registerMutationMiddleware: (callback: Middleware<MutateFunc>) => void;
getMutateWithMiddlewares: (
mutate: MutateFunc
) => (...args: Parameters<MutateFunc>) => ReturnType<MutateFunc>;
mutateWithMiddlewares: (
mutate: MutateFunc,
...args: Parameters<MutateFunc>
) => ReturnType<MutateFunc>;
unregisterMutationMiddleware: (callback: Middleware<MutateFunc>) => void;
}

Expand Down
Loading
Loading