Skip to content

Commit 06f8bc7

Browse files
committed
feat: use refs instead of global variables
1 parent 01649a7 commit 06f8bc7

File tree

1 file changed

+32
-30
lines changed

1 file changed

+32
-30
lines changed

electron/renderer/pages/grid.tsx

+32-30
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { css } from '@emotion/react';
55
import isEmpty from 'lodash-es/isEmpty.js';
66
import { useObservable, useSubscription } from 'observable-hooks';
77
import type { KeyboardEventHandler, ReactNode } from 'react';
8-
import { useCallback, useEffect, useState } from 'react';
8+
import { useCallback, useEffect, useRef, useState } from 'react';
99
import * as rxjs from 'rxjs';
1010
import { v4 as uuid } from 'uuid';
1111
import { getExperienceMindState } from '../../common/game/get-experience-mindstate.js';
@@ -33,20 +33,20 @@ import type { GameLogLine } from '../types/game.types.js';
3333
// https://nextjs.org/docs/messages/react-hydration-error
3434
const GridNoSSR = NoSSR(Grid);
3535

36-
// I started tracking these via `useState` but when calling their setter
37-
// the value did not update fast enough before a text game event
38-
// was received, resulting in text routing to the wrong stream window
39-
// or not formatting correctly. So I moved them to global variables.
40-
let gameStreamId = '';
41-
let textOutputClass = '';
42-
let textStylePreset = '';
43-
let textStyleBold = false;
44-
4536
const GridPage: React.FC = (): ReactNode => {
4637
const logger = useLogger('page:grid');
4738

39+
// I started tracking these via `useState` but when calling their setter
40+
// the value did not update fast enough before a text game event
41+
// was received, resulting in text routing to the wrong stream window
42+
// or not formatting correctly. So I moved them to refs instead.
43+
const gameStreamIdRef = useRef<string>('');
44+
const textOutputClassRef = useRef<string>('');
45+
const textStylePresetRef = useRef<string>('');
46+
const textStyleBoldRef = useRef<boolean>(false);
47+
4848
// Game events will be emitted from the IPC `game:event` channel.
49-
// Here we subscribe and route them to the correct grid item.
49+
// This page subscribes and routes them to the correct grid item.
5050
const gameEventsSubject$ = useObservable(() => {
5151
return new rxjs.Subject<GameEvent>();
5252
});
@@ -60,31 +60,33 @@ const GridPage: React.FC = (): ReactNode => {
6060

6161
const { euiTheme } = useEuiTheme();
6262

63-
// Do no memoize this function with `useCallback` or `useMemo`
64-
// because it needs to reference the current values of both
65-
// tracked and non-tracked variables.
66-
// If we memoize it then stale values would be used.
67-
const computeTextStyles = (): SerializedStyles => {
68-
// TODO user pref for 'mono' or 'serif' font family and size
69-
let fontFamily = `Verdana, ${euiTheme.font.familySerif}`;
63+
const computeTextStyles = useCallback((): SerializedStyles => {
64+
// TODO user pref for 'mono' or 'serif' font family
65+
let fontFamily = euiTheme.font.familySerif;
66+
// TODO user pref for font size
7067
let fontSize = '14px';
7168
let fontWeight = euiTheme.font.weight.regular;
7269
let fontColor = euiTheme.colors.text;
7370

74-
if (textOutputClass === 'mono') {
75-
fontFamily = `${euiTheme.font.familyCode}`;
71+
if (textOutputClassRef.current === 'mono') {
72+
fontFamily = euiTheme.font.familyCode;
7673
fontSize = euiTheme.size.m;
7774
}
7875

79-
if (textStyleBold) {
76+
if (textStyleBoldRef.current) {
8077
fontWeight = euiTheme.font.weight.bold;
8178
}
8279

83-
if (textStylePreset === 'roomName') {
80+
if (textStylePresetRef.current === 'roomName') {
8481
fontColor = euiTheme.colors.title;
8582
fontWeight = euiTheme.font.weight.bold;
8683
}
8784

85+
// TODO rather than return the calculated CSS styles,
86+
// return an object that indicates with keys from the euiTheme to use
87+
// For example, { fontFamily: 'code', fontSize: 'm', fontWeight: 'bold', color: 'title' }
88+
// This will allow the GameStreamText component to apply the correct styles
89+
// when the user's swaps the theme from light to dark mode
8890
const textStyles = css({
8991
fontFamily,
9092
fontSize,
@@ -96,7 +98,7 @@ const GridPage: React.FC = (): ReactNode => {
9698
});
9799

98100
return textStyles;
99-
};
101+
}, [euiTheme]);
100102

101103
// TODO refactor to a ExperienceGameStream component
102104
// it will know all skills to render and can highlight
@@ -165,27 +167,27 @@ const GridPage: React.FC = (): ReactNode => {
165167
});
166168
break;
167169
case GameEventType.PUSH_STREAM:
168-
gameStreamId = gameEvent.streamId;
170+
gameStreamIdRef.current = gameEvent.streamId;
169171
break;
170172
case GameEventType.POP_STREAM:
171-
gameStreamId = '';
173+
gameStreamIdRef.current = '';
172174
break;
173175
case GameEventType.PUSH_BOLD:
174-
textStyleBold = true;
176+
textStyleBoldRef.current = true;
175177
break;
176178
case GameEventType.POP_BOLD:
177-
textStyleBold = false;
179+
textStyleBoldRef.current = false;
178180
break;
179181
case GameEventType.TEXT_OUTPUT_CLASS:
180-
textOutputClass = gameEvent.textOutputClass;
182+
textOutputClassRef.current = gameEvent.textOutputClass;
181183
break;
182184
case GameEventType.TEXT_STYLE_PRESET:
183-
textStylePreset = gameEvent.textStylePreset;
185+
textStylePresetRef.current = gameEvent.textStylePreset;
184186
break;
185187
case GameEventType.TEXT:
186188
gameLogLineSubject$.next({
187189
eventId: gameEvent.eventId,
188-
streamId: gameStreamId,
190+
streamId: gameStreamIdRef.current,
189191
styles: textStyles,
190192
text: gameEvent.text,
191193
});

0 commit comments

Comments
 (0)