Skip to content

Commit 32641a9

Browse files
committed
Improve side effects handling depending on the mutationMode
1 parent ff72da9 commit 32641a9

File tree

2 files changed

+129
-90
lines changed

2 files changed

+129
-90
lines changed

packages/ra-ui-materialui/src/button/UpdateWithConfirmButton.stories.tsx

Lines changed: 103 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import polyglotI18nProvider from 'ra-i18n-polyglot';
33
import englishMessages from 'ra-language-english';
44
import frenchMessages from 'ra-language-french';
5-
import { Resource, TestMemoryRouter } from 'ra-core';
5+
import { MutationMode, Resource, TestMemoryRouter } from 'ra-core';
66
import fakeRestDataProvider from 'ra-data-fakerest';
77
import { Alert } from '@mui/material';
88
import { UpdateWithConfirmButton } from './UpdateWithConfirmButton';
@@ -82,89 +82,93 @@ const i18nProviderDefault = polyglotI18nProvider(
8282
]
8383
);
8484

85-
const dataProvider = fakeRestDataProvider({
86-
books: [
87-
{
88-
id: 1,
89-
title: 'War and Peace',
90-
author: 'Leo Tolstoy',
91-
year: 1869,
92-
},
93-
{
94-
id: 2,
95-
title: 'Pride and Predjudice',
96-
author: 'Jane Austen',
97-
year: 1813,
98-
},
99-
{
100-
id: 3,
101-
title: 'The Picture of Dorian Gray',
102-
author: 'Oscar Wilde',
103-
year: 1890,
104-
},
105-
{
106-
id: 4,
107-
title: 'Le Petit Prince',
108-
author: 'Antoine de Saint-Exupéry',
109-
year: 1943,
110-
},
111-
{
112-
id: 5,
113-
title: "Alice's Adventures in Wonderland",
114-
author: 'Lewis Carroll',
115-
year: 1865,
116-
},
117-
{
118-
id: 6,
119-
title: 'Madame Bovary',
120-
author: 'Gustave Flaubert',
121-
year: 1856,
122-
},
123-
{
124-
id: 7,
125-
title: 'The Lord of the Rings',
126-
author: 'J. R. R. Tolkien',
127-
year: 1954,
128-
},
129-
{
130-
id: 8,
131-
title: "Harry Potter and the Philosopher's Stone",
132-
author: 'J. K. Rowling',
133-
year: 1997,
134-
},
135-
{
136-
id: 9,
137-
title: 'The Alchemist',
138-
author: 'Paulo Coelho',
139-
year: 1988,
140-
},
141-
{
142-
id: 10,
143-
title: 'A Catcher in the Rye',
144-
author: 'J. D. Salinger',
145-
year: 1951,
146-
},
147-
{
148-
id: 11,
149-
title: 'Ulysses',
150-
author: 'James Joyce',
151-
year: 1922,
152-
},
153-
],
154-
authors: [
155-
{ id: 1, fullName: 'Leo Tolstoy' },
156-
{ id: 2, fullName: 'Jane Austen' },
157-
{ id: 3, fullName: 'Oscar Wilde' },
158-
{ id: 4, fullName: 'Antoine de Saint-Exupéry' },
159-
{ id: 5, fullName: 'Lewis Carroll' },
160-
{ id: 6, fullName: 'Gustave Flaubert' },
161-
{ id: 7, fullName: 'J. R. R. Tolkien' },
162-
{ id: 8, fullName: 'J. K. Rowling' },
163-
{ id: 9, fullName: 'Paulo Coelho' },
164-
{ id: 10, fullName: 'J. D. Salinger' },
165-
{ id: 11, fullName: 'James Joyce' },
166-
],
167-
});
85+
const dataProvider = fakeRestDataProvider(
86+
{
87+
books: [
88+
{
89+
id: 1,
90+
title: 'War and Peace',
91+
author: 'Leo Tolstoy',
92+
year: 1869,
93+
},
94+
{
95+
id: 2,
96+
title: 'Pride and Predjudice',
97+
author: 'Jane Austen',
98+
year: 1813,
99+
},
100+
{
101+
id: 3,
102+
title: 'The Picture of Dorian Gray',
103+
author: 'Oscar Wilde',
104+
year: 1890,
105+
},
106+
{
107+
id: 4,
108+
title: 'Le Petit Prince',
109+
author: 'Antoine de Saint-Exupéry',
110+
year: 1943,
111+
},
112+
{
113+
id: 5,
114+
title: "Alice's Adventures in Wonderland",
115+
author: 'Lewis Carroll',
116+
year: 1865,
117+
},
118+
{
119+
id: 6,
120+
title: 'Madame Bovary',
121+
author: 'Gustave Flaubert',
122+
year: 1856,
123+
},
124+
{
125+
id: 7,
126+
title: 'The Lord of the Rings',
127+
author: 'J. R. R. Tolkien',
128+
year: 1954,
129+
},
130+
{
131+
id: 8,
132+
title: "Harry Potter and the Philosopher's Stone",
133+
author: 'J. K. Rowling',
134+
year: 1997,
135+
},
136+
{
137+
id: 9,
138+
title: 'The Alchemist',
139+
author: 'Paulo Coelho',
140+
year: 1988,
141+
},
142+
{
143+
id: 10,
144+
title: 'A Catcher in the Rye',
145+
author: 'J. D. Salinger',
146+
year: 1951,
147+
},
148+
{
149+
id: 11,
150+
title: 'Ulysses',
151+
author: 'James Joyce',
152+
year: 1922,
153+
},
154+
],
155+
authors: [
156+
{ id: 1, fullName: 'Leo Tolstoy' },
157+
{ id: 2, fullName: 'Jane Austen' },
158+
{ id: 3, fullName: 'Oscar Wilde' },
159+
{ id: 4, fullName: 'Antoine de Saint-Exupéry' },
160+
{ id: 5, fullName: 'Lewis Carroll' },
161+
{ id: 6, fullName: 'Gustave Flaubert' },
162+
{ id: 7, fullName: 'J. R. R. Tolkien' },
163+
{ id: 8, fullName: 'J. K. Rowling' },
164+
{ id: 9, fullName: 'Paulo Coelho' },
165+
{ id: 10, fullName: 'J. D. Salinger' },
166+
{ id: 11, fullName: 'James Joyce' },
167+
],
168+
},
169+
process.env.NODE_ENV !== 'test',
170+
process.env.NODE_ENV !== 'test' ? 300 : 0
171+
);
168172

169173
const BookList = ({ children }) => {
170174
return (
@@ -192,7 +196,7 @@ const AuthorList = ({ children }) => {
192196
);
193197
};
194198

195-
export const Basic = () => (
199+
export const Basic = ({ mutationMode }: { mutationMode?: MutationMode }) => (
196200
<TestMemoryRouter initialEntries={['/books']}>
197201
<AdminContext dataProvider={dataProvider} i18nProvider={i18nProvider}>
198202
<AdminUI>
@@ -202,6 +206,7 @@ export const Basic = () => (
202206
<BookList>
203207
<UpdateWithConfirmButton
204208
data={{ title: 'modified' }}
209+
mutationMode={mutationMode}
205210
/>
206211
</BookList>
207212
}
@@ -211,6 +216,19 @@ export const Basic = () => (
211216
</TestMemoryRouter>
212217
);
213218

219+
Basic.args = {
220+
mutationMode: 'pessimistic',
221+
};
222+
223+
Basic.argTypes = {
224+
mutationMode: {
225+
options: ['pessimistic', 'optimistic', 'undoable'],
226+
control: {
227+
type: 'select',
228+
},
229+
},
230+
};
231+
214232
export const WithCustomTitleAndContent = () => (
215233
<TestMemoryRouter initialEntries={['/books']}>
216234
<AdminContext

packages/ra-ui-materialui/src/button/UpdateWithConfirmButton.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,40 @@ export const UpdateWithConfirmButton = <
5252
const { handleUpdate, isPending } = useUpdateController({
5353
...rest,
5454
mutationMode,
55+
mutationOptions: {
56+
...rest.mutationOptions,
57+
onSettled(data, error, variables, context) {
58+
// In pessimistic mode, we wait for the mutation to be completed (either successfully or with an error) before closing
59+
if (mutationMode === 'pessimistic') {
60+
setOpen(false);
61+
}
62+
rest.mutationOptions?.onSettled?.(
63+
data,
64+
error,
65+
variables,
66+
context
67+
);
68+
},
69+
},
5570
});
5671

57-
const handleClick = (e: React.MouseEvent) => {
58-
setOpen(true);
72+
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
5973
e.stopPropagation();
74+
setOpen(true);
6075
};
6176

62-
const handleDialogClose = () => {
77+
const handleDialogClose = (e: React.MouseEvent) => {
78+
e?.stopPropagation();
6379
setOpen(false);
6480
};
6581

66-
const handleConfirm = e => {
67-
setOpen(false);
82+
const handleConfirm = (e: React.MouseEvent<HTMLButtonElement>) => {
83+
e.stopPropagation();
84+
// We close the dialog immediately here for optimistic/undoable modes instead of in onSuccess/onError
85+
// to avoid reimplementing the default side effects
86+
if (mutationMode !== 'pessimistic') {
87+
setOpen(false);
88+
}
6889
handleUpdate(data);
6990

7091
if (typeof onClick === 'function') {

0 commit comments

Comments
 (0)