Skip to content

Commit b4b9430

Browse files
authored
HintEditor: migrate to React refs (#1558)
## Summary: This PR migrates the HintEditor to use React refs instead of legacy string refs. This improves safety. Issue: LEMS-1809 ## Test plan: `yarn tsc` `yarn test` Author: jeremywiebe Reviewers: benchristel, nishasy, jeremywiebe Required Reviewers: Approved By: nishasy, benchristel Checks: ✅ codecov/project, ❌ codecov/patch, ✅ Upload Coverage (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ gerald Pull Request URL: #1558
1 parent 9e18d81 commit b4b9430

File tree

2 files changed

+21
-28
lines changed

2 files changed

+21
-28
lines changed

.changeset/big-plums-confess.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@khanacademy/perseus-editor": patch
3+
---
4+
5+
HintEditor: migrate to React refs

packages/perseus-editor/src/hint-editor.tsx

+16-28
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ type CombinedHintsEditorProps = {
301301
*/
302302
class CombinedHintsEditor extends React.Component<CombinedHintsEditorProps> {
303303
static HintEditor: typeof HintEditor = HintEditor;
304+
hintEditors: Record<number, CombinedHintEditor | null> = {};
304305

305306
static defaultProps: {
306307
highlightLint: boolean;
@@ -353,9 +354,7 @@ class CombinedHintsEditor extends React.Component<CombinedHintsEditorProps> {
353354
const hint = hints.splice(i, 1)[0];
354355
hints.splice(i + dir, 0, hint);
355356
this.props.onChange({hints: hints}, () => {
356-
// eslint-disable-next-line react/no-string-refs
357-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
358-
this.refs["hintEditor" + (i + dir)].focus();
357+
this.hintEditors[i + dir]?.focus();
359358
});
360359
};
361360

@@ -365,42 +364,29 @@ class CombinedHintsEditor extends React.Component<CombinedHintsEditorProps> {
365364
]);
366365
this.props.onChange({hints: hints}, () => {
367366
const i = hints.length - 1;
368-
// eslint-disable-next-line react/no-string-refs
369-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
370-
this.refs["hintEditor" + i].focus();
367+
this.hintEditors[i]?.focus();
371368
});
372369
};
373370

374371
getSaveWarnings: () => any = () => {
375-
return _.chain(this.props.hints)
372+
return this.props.hints
376373
.map((hint, i) => {
377-
return _.map(
378-
// eslint-disable-next-line react/no-string-refs
379-
// @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
380-
this.refs["hintEditor" + i].getSaveWarnings(),
381-
(issue) => "Hint " + (i + 1) + ": " + issue,
382-
);
374+
return this.hintEditors[i]
375+
?.getSaveWarnings()
376+
.map((issue) => "Hint " + (i + 1) + ": " + issue);
383377
})
384-
.flatten(true)
385-
.value();
378+
.flat();
386379
};
387380

388-
serialize: (options?: any) => ReadonlyArray<PerseusRenderer> = (
389-
options: any,
390-
) => {
381+
serialize(options?: any): ReadonlyArray<PerseusRenderer> {
391382
return this.props.hints.map((hint, i) => {
392383
return this.serializeHint(i, options);
393384
});
394-
};
385+
}
395386

396-
serializeHint: (index: number, options?: any) => PerseusRenderer = (
397-
index,
398-
options,
399-
) => {
400-
// eslint-disable-next-line react/no-string-refs
401-
// @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
402-
return this.refs["hintEditor" + index].serialize(options);
403-
};
387+
serializeHint(index: number, options?: any): PerseusRenderer {
388+
return this.hintEditors[index]!.serialize(options)!;
389+
}
404390

405391
render(): React.ReactNode {
406392
const {itemId, hints} = this.props;
@@ -409,7 +395,9 @@ class CombinedHintsEditor extends React.Component<CombinedHintsEditorProps> {
409395
(hint, i) => {
410396
return (
411397
<CombinedHintEditor
412-
ref={"hintEditor" + i}
398+
ref={(editor) => {
399+
this.hintEditors[i] = editor;
400+
}}
413401
key={"hintEditor" + i}
414402
isFirst={i === 0}
415403
isLast={i + 1 === hints.length}

0 commit comments

Comments
 (0)