Skip to content

Commit c18b64a

Browse files
committed
perf(game-bottom-bar): memoize components to reduce rerenders
1 parent ec1aec0 commit c18b64a

7 files changed

+348
-184
lines changed

electron/renderer/components/game/game-bottom-bar.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import type { ReactNode } from 'react';
2+
import { memo } from 'react';
23
import { GameCommandInput } from './game-command-input.jsx';
34
import { GameCompass } from './game-compass.jsx';
45
import { GameHands } from './game-hands.jsx';
56
import { GameRoundTime } from './game-roundtime.jsx';
7+
import { GameStatusBars } from './game-status-bars.jsx';
68
import { GameStatusIcons } from './game-status-icons.jsx';
79

8-
export const GameBottomBar: React.FC = (): ReactNode => {
10+
export const GameBottomBar: React.FC = memo((): ReactNode => {
911
return (
1012
<div
1113
css={{
@@ -34,8 +36,9 @@ export const GameBottomBar: React.FC = (): ReactNode => {
3436
</div>
3537
</div>
3638
<GameCommandInput />
39+
<GameStatusBars />
3740
</div>
3841
);
39-
};
42+
});
4043

4144
GameBottomBar.displayName = 'GameBottomBar';

electron/renderer/components/game/game-command-input.tsx

+37-18
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import type {
33
ChangeEvent,
44
KeyboardEvent,
55
KeyboardEventHandler,
6+
ReactElement,
67
ReactNode,
78
} from 'react';
8-
import { useCallback, useState } from 'react';
9+
import { useCallback, useMemo, useState } from 'react';
910
import { isEmpty } from '../../../common/string/string.utils.js';
1011
import { useCommandHistory } from '../../hooks/command-history.jsx';
1112
import { runInBackground } from '../../lib/async/run-in-background.js';
@@ -48,23 +49,41 @@ export const GameCommandInput: React.FC = (): ReactNode => {
4849
[handleOnChange]
4950
);
5051

51-
return (
52-
<div css={{ width: '100%' }}>
53-
<EuiFieldText
54-
value={input}
55-
compressed={true}
56-
fullWidth={true}
57-
autoFocus={true}
58-
autoCorrect="off"
59-
autoCapitalize="off"
60-
autoComplete="off"
61-
prepend={<EuiIcon type="arrowRight" size="s" color="primary" />}
62-
tabIndex={0}
63-
onKeyDown={onKeyDown}
64-
onChange={onChange}
65-
/>
66-
</div>
67-
);
52+
const commandIcon = useMemo((): ReactElement => {
53+
return <EuiIcon type="arrowRight" size="s" color="primary" />;
54+
}, []);
55+
56+
const commandInput = useMemo((): ReactElement => {
57+
return (
58+
<div
59+
css={{
60+
width: '100%',
61+
paddingInline: '5px',
62+
}}
63+
>
64+
<EuiFieldText
65+
css={{
66+
// Removes the bottom blue border when user focuses the field.
67+
// I found it distracting.
68+
backgroundImage: 'unset',
69+
}}
70+
value={input}
71+
compressed={true}
72+
fullWidth={true}
73+
autoFocus={true}
74+
autoCorrect="off"
75+
autoCapitalize="off"
76+
autoComplete="off"
77+
prepend={commandIcon}
78+
tabIndex={0}
79+
onKeyDown={onKeyDown}
80+
onChange={onChange}
81+
/>
82+
</div>
83+
);
84+
}, [input, commandIcon, onKeyDown, onChange]);
85+
86+
return commandInput;
6887
};
6988

7089
GameCommandInput.displayName = 'GameCommandInput';

0 commit comments

Comments
 (0)