Skip to content

Commit 4ee9640

Browse files
[cleaning-the-perseus-finddom] Initial cleanup
1 parent 48b26d9 commit 4ee9640

File tree

4 files changed

+39
-67
lines changed

4 files changed

+39
-67
lines changed

packages/perseus/src/renderer.tsx

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
} from "@khanacademy/perseus-score";
1818
import {entries} from "@khanacademy/wonder-stuff-core";
1919
import classNames from "classnames";
20-
import $ from "jquery";
2120
import * as React from "react";
2221
import ReactDOM from "react-dom";
2322
import _ from "underscore";
@@ -311,9 +310,6 @@ class Renderer
311310
componentDidMount() {
312311
this._isMounted = true;
313312

314-
// figure out why we're passing an empty object
315-
// @ts-expect-error - TS2345 - Argument of type '{}' is not assignable to parameter of type 'Props'.
316-
this.handleRender({});
317313
this._currentFocus = null;
318314

319315
this.props.initializeUserInput?.(
@@ -423,7 +419,6 @@ class Renderer
423419
}
424420

425421
componentDidUpdate(prevProps: Props, prevState: State) {
426-
this.handleRender(prevProps);
427422
// We even do this if we did reuse the markdown because
428423
// we might need to update the widget props on this render,
429424
// even though we have the same widgets.
@@ -1421,29 +1416,6 @@ class Renderer
14211416
);
14221417
};
14231418

1424-
handleRender: (prevProps: Props) => void = (prevProps: Props) => {
1425-
const onRender = this.props.onRender;
1426-
const oldOnRender = prevProps.onRender;
1427-
1428-
// In the common case of no callback specified, avoid this work.
1429-
if (onRender !== noopOnRender || oldOnRender !== noopOnRender) {
1430-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'find' does not exist on type 'JQueryStatic'.
1431-
const $images = $(ReactDOM.findDOMNode(this)).find("img");
1432-
1433-
// Fire callback on image load...
1434-
if (oldOnRender !== noopOnRender) {
1435-
$images.off("load", oldOnRender);
1436-
}
1437-
1438-
if (onRender !== noopOnRender) {
1439-
$images.on("load", onRender);
1440-
}
1441-
}
1442-
1443-
// ...as well as right now (non-image, non-TeX or image from cache)
1444-
onRender();
1445-
};
1446-
14471419
// Sets the current focus path
14481420
// If the new focus path is not a prefix of the old focus path,
14491421
// we send an onChangeFocus event back to our parent.

packages/perseus/src/widgets/matrix/matrix.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ type State = {
115115
class Matrix extends React.Component<Props, State> implements Widget {
116116
static contextType = PerseusI18nContext;
117117
declare context: React.ContextType<typeof PerseusI18nContext>;
118+
answerRefs: Record<string, SimpleKeypadInput | HTMLInputElement> = {};
118119

119120
// @ts-expect-error - TS2564 - Property 'cursorPosition' has no initializer and is not definitely assigned in the constructor.
120121
cursorPosition: [number, number];
@@ -170,9 +171,8 @@ class Matrix extends React.Component<Props, State> implements Widget {
170171

171172
focusInputPath: (arg1: any) => void = (path) => {
172173
const inputID = getRefForPath(path);
173-
// eslint-disable-next-line react/no-string-refs
174-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
175-
this.refs[inputID].focus();
174+
const inputComponent = this.answerRefs[inputID];
175+
inputComponent.focus();
176176
};
177177

178178
blurInputPath: (arg1: any) => void = (path) => {
@@ -181,15 +181,19 @@ class Matrix extends React.Component<Props, State> implements Widget {
181181
}
182182

183183
const inputID = getRefForPath(path);
184-
// eslint-disable-next-line react/no-string-refs
185-
// @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'ReactInstance'.
186-
this.refs[inputID].blur();
184+
const inputComponent = this.answerRefs[inputID];
185+
inputComponent.blur();
187186
};
188187

189188
getDOMNodeForPath(path: FocusPath) {
190189
const inputID = getRefForPath(path);
191-
// eslint-disable-next-line react/no-string-refs
192-
return ReactDOM.findDOMNode(this.refs[inputID]);
190+
const inputRef = this.answerRefs[inputID];
191+
if (this.props.apiOptions.customKeypad) {
192+
// This is a SimpleKeypadInput, so we need to find the DOM node
193+
return ReactDOM.findDOMNode(inputRef);
194+
} else {
195+
return inputRef as HTMLInputElement;
196+
}
193197
}
194198

195199
handleKeyDown: (arg1: any, arg2: any, arg3: any) => void = (
@@ -377,9 +381,13 @@ class Matrix extends React.Component<Props, State> implements Widget {
377381
className: outside
378382
? "outside"
379383
: "inside",
380-
ref: getRefForPath(
381-
getInputPath(row, col),
382-
),
384+
ref: (ref) => {
385+
this.answerRefs[
386+
getRefForPath(
387+
getInputPath(row, col),
388+
)
389+
] = ref;
390+
},
383391
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
384392
value: rowVals ? rowVals[col] : null,
385393
style: {

packages/perseus/src/widgets/number-line/number-line.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ class NumberLine extends React.Component<Props, State> implements Widget {
247247
static contextType = PerseusI18nContext;
248248
declare context: React.ContextType<typeof PerseusI18nContext>;
249249

250+
tickControlRef: SimpleKeypadInput | HTMLInputElement | null = null;
251+
250252
static defaultProps: DefaultProps = {
251253
range: [0, 10],
252254
labelStyle: "decimal",
@@ -346,27 +348,21 @@ class NumberLine extends React.Component<Props, State> implements Widget {
346348

347349
focus() {
348350
if (this.props.isTickCtrl) {
349-
// eslint-disable-next-line react/no-string-refs
350-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
351-
this.refs["tick-ctrl"].focus();
351+
this.tickControlRef?.focus();
352352
return true;
353353
}
354354
return false;
355355
}
356356

357357
focusInputPath: (arg1: any) => void = (path) => {
358358
if (path.length === 1) {
359-
// eslint-disable-next-line react/no-string-refs
360-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
361-
this.refs[path[0]].focus();
359+
this.tickControlRef?.focus();
362360
}
363361
};
364362

365363
blurInputPath: (arg1: any) => void = (path) => {
366364
if (path.length === 1) {
367-
// eslint-disable-next-line react/no-string-refs
368-
// @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'ReactInstance'.
369-
this.refs[path[0]].blur();
365+
this.tickControlRef?.blur();
370366
}
371367
};
372368

@@ -379,8 +375,7 @@ class NumberLine extends React.Component<Props, State> implements Widget {
379375

380376
getDOMNodeForPath(inputPath: FocusPath) {
381377
if (inputPath?.length === 1) {
382-
// eslint-disable-next-line react/no-string-refs
383-
return ReactDOM.findDOMNode(this.refs[inputPath[0]]);
378+
return ReactDOM.findDOMNode(this.tickControlRef);
384379
}
385380
return null;
386381
}
@@ -679,8 +674,9 @@ class NumberLine extends React.Component<Props, State> implements Widget {
679674
<label>
680675
{strings.numDivisions}{" "}
681676
<Input
682-
// eslint-disable-next-line react/no-string-refs
683-
ref="tick-ctrl"
677+
ref={(ref) => {
678+
this.tickControlRef = ref;
679+
}}
684680
value={
685681
this.state.numDivisionsEmpty
686682
? null

packages/perseus/src/widgets/table/table.tsx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {linterContextDefault} from "@khanacademy/perseus-linter";
22
import * as React from "react";
3-
import ReactDOM from "react-dom";
3+
import {findDOMNode} from "react-dom";
44

55
import {PerseusI18nContext} from "../../components/i18n-context";
66
import SimpleKeypadInput from "../../components/simple-keypad-input";
@@ -16,6 +16,7 @@ import type {
1616
PerseusTableWidgetOptions,
1717
PerseusTableUserInput,
1818
} from "@khanacademy/perseus-core";
19+
import type ReactDOM from "react-dom";
1920

2021
const {assert} = InteractiveUtil;
2122

@@ -76,7 +77,7 @@ class Table extends React.Component<Props> implements Widget {
7677
static contextType = PerseusI18nContext;
7778
declare context: React.ContextType<typeof PerseusI18nContext>;
7879
headerRefs: Record<string, any> = {};
79-
answerRefs: Record<string, any> = {};
80+
answerRefs: Record<string, SimpleKeypadInput | HTMLInputElement> = {};
8081

8182
static defaultProps: DefaultProps = {
8283
apiOptions: ApiOptions.defaults,
@@ -138,31 +139,26 @@ class Table extends React.Component<Props> implements Widget {
138139
focusInputPath(path: FocusPath): void {
139140
const inputID = getRefForPath(path as Path);
140141
const inputComponent = this.answerRefs[inputID];
141-
if (this.props.apiOptions.customKeypad) {
142-
inputComponent.focus();
143-
} else {
144-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
145-
ReactDOM.findDOMNode(inputComponent).focus();
146-
}
142+
inputComponent.focus();
147143
}
148144

149145
blurInputPath(path: FocusPath): void {
150146
const inputID = getRefForPath(path as Path);
151147
const inputComponent = this.answerRefs[inputID];
152-
if (this.props.apiOptions.customKeypad) {
153-
inputComponent.blur();
154-
} else {
155-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
156-
ReactDOM.findDOMNode(inputComponent).blur();
157-
}
148+
inputComponent.blur();
158149
}
159150

160151
getDOMNodeForPath(
161152
path: FocusPath,
162153
): ReturnType<typeof ReactDOM.findDOMNode> {
163154
const inputID = getRefForPath(path as Path);
164155
const inputRef = this.answerRefs[inputID];
165-
return ReactDOM.findDOMNode(inputRef);
156+
157+
if (this.props.apiOptions.customKeypad) {
158+
return findDOMNode(inputRef);
159+
} else {
160+
return inputRef as HTMLInputElement;
161+
}
166162
}
167163

168164
getInputPaths(): string[][] {

0 commit comments

Comments
 (0)