Skip to content

Commit 277fd89

Browse files
authored
Merge pull request #5613 from marmelab/list-optims
Fix useless AppBar rerenders
2 parents 3fed1f9 + c3ed422 commit 277fd89

File tree

7 files changed

+36
-12
lines changed

7 files changed

+36
-12
lines changed

examples/simple/src/Layout.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { forwardRef } from 'react';
2+
import { forwardRef, memo } from 'react';
33
import { Layout, AppBar, UserMenu, useLocale, useSetLocale } from 'react-admin';
44
import { MenuItem, ListItemIcon } from '@material-ui/core';
55
import { makeStyles } from '@material-ui/core/styles';
@@ -39,6 +39,6 @@ const MyUserMenu = props => (
3939
</UserMenu>
4040
);
4141

42-
const MyAppBar = props => <AppBar {...props} userMenu={<MyUserMenu />} />;
42+
const MyAppBar = memo(props => <AppBar {...props} userMenu={<MyUserMenu />} />);
4343

4444
export default props => <Layout {...props} appBar={MyAppBar} />;

examples/simple/src/posts/PostList.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ const PostList = props => {
160160
reference="tags"
161161
source="tags"
162162
sortBy="tags.name"
163-
sort={{ field: 'name', order: 'ASC' }}
163+
sort={tagSort}
164164
cellClassName={classes.hiddenOnSmallScreens}
165165
headerClassName={classes.hiddenOnSmallScreens}
166166
>
@@ -178,4 +178,6 @@ const PostList = props => {
178178
);
179179
};
180180

181+
const tagSort = { field: 'name', order: 'ASC' };
182+
181183
export default PostList;

packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface Option {
2424
source: string;
2525
}
2626

27+
const emptyArray = [];
2728
const defaultFilter = {};
2829
const defaultSort = { field: null, order: null };
2930

@@ -65,7 +66,7 @@ const useReferenceArrayFieldController = (
6566
} = props;
6667
const resource = useResourceContext(props);
6768
const notify = useNotify();
68-
const ids = get(record, source) || [];
69+
const ids = get(record, source) || emptyArray;
6970
const { data, error, loading, loaded } = useGetMany(reference, ids, {
7071
onFailure: error =>
7172
notify(

packages/ra-core/src/core/CoreAdminUI.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import * as React from 'react';
2-
import { createElement, FunctionComponent, ComponentType } from 'react';
2+
import {
3+
createElement,
4+
FunctionComponent,
5+
ComponentType,
6+
useMemo,
7+
} from 'react';
38
import { Switch, Route } from 'react-router-dom';
49

510
import CoreAdminRouter from './CoreAdminRouter';
@@ -54,6 +59,9 @@ const CoreAdminUI: FunctionComponent<AdminUIProps> = ({
5459
theme,
5560
title = 'React Admin',
5661
}) => {
62+
const logoutElement = useMemo(() => logout && createElement(logout), [
63+
logout,
64+
]);
5765
return (
5866
<Switch>
5967
{loginPage !== false && loginPage !== true ? (
@@ -78,7 +86,7 @@ const CoreAdminUI: FunctionComponent<AdminUIProps> = ({
7886
dashboard={dashboard}
7987
layout={layout}
8088
loading={loading}
81-
logout={logout && createElement(logout)}
89+
logout={logoutElement}
8290
menu={menu}
8391
ready={ready}
8492
theme={theme}

packages/ra-ui-materialui/src/field/BooleanField.spec.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ describe('<BooleanField />', () => {
1515
it('should display tick and truthy text if value is true', () => {
1616
const { queryByTitle } = render(<BooleanField {...defaultProps} />);
1717
expect(queryByTitle('ra.boolean.true')).not.toBeNull();
18-
expect(queryByTitle('ra.boolean.true').dataset.testid).toBe('true');
18+
expect(
19+
(queryByTitle('ra.boolean.true').firstChild as HTMLElement).dataset
20+
.testid
21+
).toBe('true');
1922
expect(queryByTitle('ra.boolean.false')).toBeNull();
2023
});
2124

@@ -39,7 +42,10 @@ describe('<BooleanField />', () => {
3942
);
4043
expect(queryByTitle('ra.boolean.true')).toBeNull();
4144
expect(queryByTitle('ra.boolean.false')).not.toBeNull();
42-
expect(queryByTitle('ra.boolean.false').dataset.testid).toBe('false');
45+
expect(
46+
(queryByTitle('ra.boolean.false').firstChild as HTMLElement).dataset
47+
.testid
48+
).toBe('false');
4349
});
4450

4551
it('should use valueLabelFalse for custom falsy text', () => {

packages/ra-ui-materialui/src/field/BooleanField.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,16 @@ export const BooleanField: FC<BooleanFieldProps> = memo<BooleanFieldProps>(
5959
>
6060
<Tooltip title={translate(ariaLabel, { _: ariaLabel })}>
6161
{value === true ? (
62-
<TrueIcon data-testid="true" fontSize="small" />
62+
<span>
63+
<TrueIcon data-testid="true" fontSize="small" />
64+
</span>
6365
) : (
64-
<FalseIcon data-testid="false" fontSize="small" />
66+
<span>
67+
<FalseIcon
68+
data-testid="false"
69+
fontSize="small"
70+
/>
71+
</span>
6572
)}
6673
</Tooltip>
6774
</Typography>

packages/ra-ui-materialui/src/layout/AppBar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { Children, cloneElement } from 'react';
2+
import { Children, cloneElement, memo } from 'react';
33
import PropTypes from 'prop-types';
44
import { useDispatch } from 'react-redux';
55
import classNames from 'classnames';
@@ -195,4 +195,4 @@ export interface AppBarProps extends Omit<MuiAppBarProps, 'title' | 'classes'> {
195195
userMenu?: JSX.Element | boolean;
196196
}
197197

198-
export default AppBar;
198+
export default memo(AppBar);

0 commit comments

Comments
 (0)