Skip to content

Commit 3d9f34e

Browse files
Naiely convert to function component
1 parent c124192 commit 3d9f34e

File tree

1 file changed

+94
-134
lines changed

1 file changed

+94
-134
lines changed

extensions/ql-vscode/src/view/results/ResultTables.tsx

Lines changed: 94 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { vscode } from "../vscode-api";
2424
import { sendTelemetry } from "../common/telemetry";
2525
import { ResultTable } from "./ResultTable";
2626
import { ResultTablesHeader } from "./ResultTablesHeader";
27+
import { useEffect } from "react";
2728

2829
/**
2930
* Properties for the `ResultTables` component.
@@ -43,14 +44,6 @@ interface ResultTablesProps {
4344
queryPath: string;
4445
}
4546

46-
/**
47-
* State for the `ResultTables` component.
48-
*/
49-
interface ResultTablesState {
50-
selectedTable: string; // name of selected result set
51-
problemsViewSelected: boolean;
52-
}
53-
5447
const UPDATING_RESULTS_TEXT_CLASS_NAME =
5548
"vscode-codeql__result-tables-updating-text";
5649

@@ -122,85 +115,71 @@ function getResultSets(
122115
* Displays multiple `ResultTable` tables, where the table to be displayed is selected by a
123116
* dropdown.
124117
*/
125-
export class ResultTables extends React.Component<
126-
ResultTablesProps,
127-
ResultTablesState
128-
> {
129-
constructor(props: ResultTablesProps) {
130-
super(props);
131-
const selectedTable =
132-
props.parsedResultSets.selectedTable ||
133-
getDefaultResultSet(
134-
getResultSets(props.rawResultSets, props.interpretation),
135-
);
136-
this.state = {
137-
selectedTable,
138-
problemsViewSelected: false,
139-
};
140-
}
118+
export function ResultTables(props: ResultTablesProps) {
119+
const {
120+
parsedResultSets,
121+
rawResultSets,
122+
interpretation,
123+
database,
124+
resultsPath,
125+
metadata,
126+
origResultsPaths,
127+
isLoadingNewResults,
128+
sortStates,
129+
} = props;
141130

142-
handleMessage(msg: IntoResultsViewMsg): void {
131+
const [selectedTable, setSelectedTable] = React.useState(
132+
parsedResultSets.selectedTable ||
133+
getDefaultResultSet(getResultSets(rawResultSets, interpretation)),
134+
);
135+
const [problemsViewSelected, setProblemsViewSelected] = React.useState(false);
136+
137+
const handleMessage = (msg: IntoResultsViewMsg): void => {
143138
switch (msg.t) {
144139
case "untoggleShowProblems":
145-
this.setState({
146-
problemsViewSelected: false,
147-
});
140+
setProblemsViewSelected(false);
148141
break;
149142

150143
default:
151144
// noop
152145
}
153-
}
146+
};
154147

155-
private vscodeMessageHandler(evt: MessageEvent) {
148+
const vscodeMessageHandler = (evt: MessageEvent): void => {
156149
// sanitize origin
157150
const origin = evt.origin.replace(/\n|\r/g, "");
158151
evt.origin === window.origin
159-
? this.handleMessage(evt.data as IntoResultsViewMsg)
152+
? handleMessage(evt.data as IntoResultsViewMsg)
160153
: console.error(`Invalid event origin ${origin}`);
161-
}
154+
};
162155

163156
// TODO: Duplicated from results.tsx consider a way to
164157
// avoid this duplication
165-
componentDidMount(): void {
166-
this.vscodeMessageHandler = this.vscodeMessageHandler.bind(this);
167-
window.addEventListener("message", this.vscodeMessageHandler);
168-
}
158+
useEffect(() => {
159+
window.addEventListener("message", vscodeMessageHandler);
169160

170-
componentWillUnmount(): void {
171-
if (this.vscodeMessageHandler) {
172-
window.removeEventListener("message", this.vscodeMessageHandler);
173-
}
174-
}
161+
return () => {
162+
window.removeEventListener("message", vscodeMessageHandler);
163+
};
164+
}, []);
175165

176-
componentDidUpdate(
177-
prevProps: Readonly<ResultTablesProps>,
178-
prevState: Readonly<ResultTablesState>,
179-
snapshot?: any,
180-
) {
166+
useEffect(() => {
181167
const resultSetExists =
182-
this.props.parsedResultSets.resultSetNames.some(
183-
(v) => this.state.selectedTable === v,
184-
) ||
185-
getResultSets(this.props.rawResultSets, this.props.interpretation).some(
186-
(v) => this.state.selectedTable === v.schema.name,
168+
parsedResultSets.resultSetNames.some((v) => selectedTable === v) ||
169+
getResultSets(rawResultSets, interpretation).some(
170+
(v) => selectedTable === v.schema.name,
187171
);
188172

189173
// If the selected result set does not exist, select the default result set.
190174
if (!resultSetExists) {
191-
this.setState((state, props) => {
192-
const selectedTable =
193-
props.parsedResultSets.selectedTable ||
194-
getDefaultResultSet(
195-
getResultSets(props.rawResultSets, props.interpretation),
196-
);
197-
198-
return { selectedTable };
199-
});
175+
setSelectedTable(
176+
parsedResultSets.selectedTable ||
177+
getDefaultResultSet(getResultSets(rawResultSets, interpretation)),
178+
);
200179
}
201-
}
180+
});
202181

203-
private onTableSelectionChange = (
182+
const onTableSelectionChange = (
204183
event: React.ChangeEvent<HTMLSelectElement>,
205184
): void => {
206185
const selectedTable = event.target.value;
@@ -212,16 +191,13 @@ export class ResultTables extends React.Component<
212191
sendTelemetry("local-results-table-selection");
213192
};
214193

215-
private alertTableExtras(): JSX.Element | undefined {
216-
const { database, resultsPath, metadata, origResultsPaths } = this.props;
194+
const alertTableExtras = (): JSX.Element | undefined => {
217195
const handleCheckboxChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
218-
if (e.target.checked === this.state.problemsViewSelected) {
196+
if (e.target.checked === problemsViewSelected) {
219197
// no change
220198
return;
221199
}
222-
this.setState({
223-
problemsViewSelected: e.target.checked,
224-
});
200+
setProblemsViewSelected(e.target.checked);
225201
if (e.target.checked) {
226202
sendTelemetry("local-results-show-results-in-problems-view");
227203
}
@@ -244,85 +220,69 @@ export class ResultTables extends React.Component<
244220
id="toggle-diagnostics"
245221
name="toggle-diagnostics"
246222
onChange={handleCheckboxChanged}
247-
checked={this.state.problemsViewSelected}
223+
checked={problemsViewSelected}
248224
/>
249225
<label htmlFor="toggle-diagnostics">
250226
Show results in Problems view
251227
</label>
252228
</div>
253229
</div>
254230
);
255-
}
231+
};
256232

257-
getOffset(): number {
258-
const { parsedResultSets } = this.props;
233+
const getOffset = (): number => {
259234
return parsedResultSets.pageNumber * parsedResultSets.pageSize;
260-
}
235+
};
261236

262-
render(): React.ReactNode {
263-
const { selectedTable } = this.state;
264-
const resultSets = getResultSets(
265-
this.props.rawResultSets,
266-
this.props.interpretation,
267-
);
268-
const resultSetNames = getResultSetNames(
269-
this.props.interpretation,
270-
this.props.parsedResultSets,
271-
);
237+
const resultSets = getResultSets(rawResultSets, interpretation);
238+
const resultSetNames = getResultSetNames(interpretation, parsedResultSets);
272239

273-
const resultSet = resultSets.find(
274-
(resultSet) => resultSet.schema.name === selectedTable,
275-
);
276-
const nonemptyRawResults = resultSets.some(
277-
(resultSet) =>
278-
resultSet.t === "RawResultSet" && resultSet.rows.length > 0,
279-
);
280-
const numberOfResults = resultSet && renderResultCountString(resultSet);
240+
const resultSet = resultSets.find(
241+
(resultSet) => resultSet.schema.name === selectedTable,
242+
);
243+
const nonemptyRawResults = resultSets.some(
244+
(resultSet) => resultSet.t === "RawResultSet" && resultSet.rows.length > 0,
245+
);
246+
const numberOfResults = resultSet && renderResultCountString(resultSet);
281247

282-
const resultSetOptions = resultSetNames.map((name) => (
283-
<option key={name} value={name}>
284-
{name}
285-
</option>
286-
));
287-
return (
288-
<div>
289-
<ResultTablesHeader
290-
{...this.props}
291-
selectedTable={this.state.selectedTable}
292-
/>
293-
<div className={tableHeaderClassName}></div>
294-
<div className={tableHeaderClassName}>
295-
<select value={selectedTable} onChange={this.onTableSelectionChange}>
296-
{resultSetOptions}
297-
</select>
298-
{numberOfResults}
299-
{selectedTable === ALERTS_TABLE_NAME
300-
? this.alertTableExtras()
301-
: undefined}
302-
{this.props.isLoadingNewResults ? (
303-
<span className={UPDATING_RESULTS_TEXT_CLASS_NAME}>
304-
Updating results…
305-
</span>
306-
) : null}
307-
</div>
308-
{resultSet && (
309-
<ResultTable
310-
key={resultSet.schema.name}
311-
resultSet={resultSet}
312-
databaseUri={this.props.database.databaseUri}
313-
resultsPath={this.props.resultsPath}
314-
sortState={this.props.sortStates.get(resultSet.schema.name)}
315-
nonemptyRawResults={nonemptyRawResults}
316-
showRawResults={() => {
317-
this.setState({ selectedTable: SELECT_TABLE_NAME });
318-
sendTelemetry("local-results-show-raw-results");
319-
}}
320-
offset={this.getOffset()}
321-
/>
322-
)}
248+
const resultSetOptions = resultSetNames.map((name) => (
249+
<option key={name} value={name}>
250+
{name}
251+
</option>
252+
));
253+
return (
254+
<div>
255+
<ResultTablesHeader {...props} selectedTable={selectedTable} />
256+
<div className={tableHeaderClassName}></div>
257+
<div className={tableHeaderClassName}>
258+
<select value={selectedTable} onChange={onTableSelectionChange}>
259+
{resultSetOptions}
260+
</select>
261+
{numberOfResults}
262+
{selectedTable === ALERTS_TABLE_NAME ? alertTableExtras() : undefined}
263+
{isLoadingNewResults ? (
264+
<span className={UPDATING_RESULTS_TEXT_CLASS_NAME}>
265+
Updating results…
266+
</span>
267+
) : null}
323268
</div>
324-
);
325-
}
269+
{resultSet && (
270+
<ResultTable
271+
key={resultSet.schema.name}
272+
resultSet={resultSet}
273+
databaseUri={database.databaseUri}
274+
resultsPath={resultsPath}
275+
sortState={sortStates.get(resultSet.schema.name)}
276+
nonemptyRawResults={nonemptyRawResults}
277+
showRawResults={() => {
278+
setSelectedTable(SELECT_TABLE_NAME);
279+
sendTelemetry("local-results-show-raw-results");
280+
}}
281+
offset={getOffset()}
282+
/>
283+
)}
284+
</div>
285+
);
326286
}
327287

328288
function getDefaultResultSet(resultSets: readonly ResultSet[]): string {

0 commit comments

Comments
 (0)