From b4b9430653a45078702a667ee98ca1a19a07315f Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Thu, 29 Aug 2024 15:31:17 -0700 Subject: [PATCH] HintEditor: migrate to React refs (#1558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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: https://github.com/Khan/perseus/pull/1558 --- .changeset/big-plums-confess.md | 5 +++ packages/perseus-editor/src/hint-editor.tsx | 44 ++++++++------------- 2 files changed, 21 insertions(+), 28 deletions(-) create mode 100644 .changeset/big-plums-confess.md diff --git a/.changeset/big-plums-confess.md b/.changeset/big-plums-confess.md new file mode 100644 index 0000000000..1f69d99f2f --- /dev/null +++ b/.changeset/big-plums-confess.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus-editor": patch +--- + +HintEditor: migrate to React refs diff --git a/packages/perseus-editor/src/hint-editor.tsx b/packages/perseus-editor/src/hint-editor.tsx index 31af0da3eb..77db5e398e 100644 --- a/packages/perseus-editor/src/hint-editor.tsx +++ b/packages/perseus-editor/src/hint-editor.tsx @@ -301,6 +301,7 @@ type CombinedHintsEditorProps = { */ class CombinedHintsEditor extends React.Component { static HintEditor: typeof HintEditor = HintEditor; + hintEditors: Record = {}; static defaultProps: { highlightLint: boolean; @@ -353,9 +354,7 @@ class CombinedHintsEditor extends React.Component { const hint = hints.splice(i, 1)[0]; hints.splice(i + dir, 0, hint); this.props.onChange({hints: hints}, () => { - // eslint-disable-next-line react/no-string-refs - // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'. - this.refs["hintEditor" + (i + dir)].focus(); + this.hintEditors[i + dir]?.focus(); }); }; @@ -365,42 +364,29 @@ class CombinedHintsEditor extends React.Component { ]); this.props.onChange({hints: hints}, () => { const i = hints.length - 1; - // eslint-disable-next-line react/no-string-refs - // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'. - this.refs["hintEditor" + i].focus(); + this.hintEditors[i]?.focus(); }); }; getSaveWarnings: () => any = () => { - return _.chain(this.props.hints) + return this.props.hints .map((hint, i) => { - return _.map( - // eslint-disable-next-line react/no-string-refs - // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'. - this.refs["hintEditor" + i].getSaveWarnings(), - (issue) => "Hint " + (i + 1) + ": " + issue, - ); + return this.hintEditors[i] + ?.getSaveWarnings() + .map((issue) => "Hint " + (i + 1) + ": " + issue); }) - .flatten(true) - .value(); + .flat(); }; - serialize: (options?: any) => ReadonlyArray = ( - options: any, - ) => { + serialize(options?: any): ReadonlyArray { return this.props.hints.map((hint, i) => { return this.serializeHint(i, options); }); - }; + } - serializeHint: (index: number, options?: any) => PerseusRenderer = ( - index, - options, - ) => { - // eslint-disable-next-line react/no-string-refs - // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'. - return this.refs["hintEditor" + index].serialize(options); - }; + serializeHint(index: number, options?: any): PerseusRenderer { + return this.hintEditors[index]!.serialize(options)!; + } render(): React.ReactNode { const {itemId, hints} = this.props; @@ -409,7 +395,9 @@ class CombinedHintsEditor extends React.Component { (hint, i) => { return ( { + this.hintEditors[i] = editor; + }} key={"hintEditor" + i} isFirst={i === 0} isLast={i + 1 === hints.length}