Skip to content

Commit

Permalink
Enable react hooks linting and fix issues (#3761)
Browse files Browse the repository at this point in the history
fix #3745
  • Loading branch information
timotheeguerin authored Jul 8, 2024
1 parent 53836c5 commit 4553419
Show file tree
Hide file tree
Showing 25 changed files with 133 additions and 88 deletions.
9 changes: 9 additions & 0 deletions .chronus/changes/fix-react-hooks-2024-6-8-15-40-17.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: internal
packages:
- "@typespec/html-program-viewer"
- "@typespec/playground"
---

Enable react hooks linting and fix issues
11 changes: 11 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-check
import eslint from "@eslint/js";
import deprecation from "eslint-plugin-deprecation";
import reactHooks from "eslint-plugin-react-hooks";
import unicorn from "eslint-plugin-unicorn";
import vitest from "eslint-plugin-vitest";
import { dirname } from "path";
Expand Down Expand Up @@ -105,10 +106,20 @@ const testFilesConfig = tsEslint.config({
},
});

const jsxFilesConfig = tsEslint.config({
files: ["**/*.tsx"],
plugins: { "react-hooks": reactHooks },
rules: {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
},
});

export const TypeSpecCommonEslintConfigs = [
eslint.configs.recommended,
...tsEslint.configs.recommended,
...allFilesConfig,
...jsxFilesConfig,
...testFilesConfig,
];

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"eslint": "^8.57.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-unicorn": "^54.0.0",
"eslint-plugin-vitest": "^0.5.4",
"picocolors": "~1.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const Search = ({ onBlur }: SearchProps) => {
setSearch(item.optionValue.slice(2));
}
},
[nav.selectPath, setSearch]
[nav]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const EntityUI: FunctionComponent<EntityUIProps> = ({ entity }) => {
const TypeUI: FunctionComponent<{ type: Type }> = ({ type }) => {
const nav = useTreeNavigatorOptional();

const navToType = useCallback(() => nav?.navToType(type), [nav?.navToType, type]);
const navToType = useCallback(() => nav?.navToType(type), [nav, type]);
return (
<div className={style["type-ui"]}>
<div className={style["type-ui-header"]} onClick={nav && navToType}>
Expand All @@ -54,7 +54,7 @@ const NamedTypeRef: FunctionComponent<{ type: NamedType }> = ({ type }) => {

const navToType = useCallback(() => {
nav?.navToType(type);
}, [nav?.navToType, type]);
}, [nav, type]);
return (
<a className={style["named-type-ref"]} onClick={nav && navToType}>
{getTypeName(type)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const ListTypeView = ({ nav, node }: ListTypeViewProps) => {
const Item = ({ item, nav }: { nav: TreeNavigator; item: TypeGraphNode }) => {
const select = useCallback(() => {
nav.selectPath(item.id);
}, [nav.selectPath]);
}, [item.id, nav]);
return (
<ListItem onAction={select} className={style["item"]}>
{item.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ export const DiagnosticList: FunctionComponent<DiagnosticListProps> = ({
diagnostics,
onDiagnosticSelected,
}) => {
if (diagnostics.length === 0) {
return <div className={style["list"]}>No errors</div>;
}

const handleItemSelected = useCallback(
(diagnostic: Diagnostic) => {
onDiagnosticSelected?.(diagnostic);
},
[onDiagnosticSelected]
);
if (diagnostics.length === 0) {
return <div className={style["list"]}>No errors</div>;
}
return (
<div className={style["list"]}>
{diagnostics.map((x, i) => {
Expand Down
2 changes: 2 additions & 0 deletions packages/playground/src/react/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const Editor: FunctionComponent<EditorProps> = ({ model, options, actions
...options,
});
onMount?.({ editor: editorRef.current });
// This needs special handling where we only want to run this effect once
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
Expand Down
22 changes: 10 additions & 12 deletions packages/playground/src/react/file-output/file-output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,22 @@ export const FileOutput: FunctionComponent<FileOutputProps> = ({ filename, conte
);
const keys = Object.keys(resolvedViewers);

if (keys.length === 0) {
return <>No viewers</>;
} else if (keys.length === 1) {
return resolvedViewers[keys[0]].render({ filename, content });
}

const [selected, setSelected] = useState<string>(keys[0]);

const handleSelected = useCallback(
(_: unknown, data: SelectOnChangeData) => {
setSelected(data.value);
},
[selected]
);
const handleSelected = useCallback((_: unknown, data: SelectOnChangeData) => {
setSelected(data.value);
}, []);

const selectedRender = useMemo(() => {
return resolvedViewers[selected].render;
}, [selected, resolvedViewers]);

if (keys.length === 0) {
return <>No viewers</>;
} else if (keys.length === 1) {
return resolvedViewers[keys[0]].render({ filename, content });
}

return (
<div className={style["file-output"]}>
<div className={style["viewer-selector"]}>
Expand Down
17 changes: 10 additions & 7 deletions packages/playground/src/react/output-view/file-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ const FileViewerComponent = ({
const [filename, setFilename] = useState<string>("");
const [content, setContent] = useState<string>("");

const loadOutputFile = useCallback(
async (path: string) => {
const contents = await program.host.readFile("./tsp-output/" + path);
setContent(contents.text);
},
[program.host]
);

useEffect(() => {
if (outputFiles.length > 0) {
const fileStillThere = outputFiles.find((x) => x === filename);
Expand All @@ -23,19 +31,14 @@ const FileViewerComponent = ({
} else {
setFilename("");
}
}, [program, outputFiles]);

async function loadOutputFile(path: string) {
const contents = await program.host.readFile("./tsp-output/" + path);
setContent(contents.text);
}
}, [program, outputFiles, loadOutputFile, filename]);

const handleTabSelection = useCallback(
(newFilename: string) => {
setFilename(newFilename);
void loadOutputFile(newFilename);
},
[setFilename]
[loadOutputFile]
);

if (outputFiles.length === 0) {
Expand Down
6 changes: 5 additions & 1 deletion packages/playground/src/react/output-view/output-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ export const OutputView: FunctionComponent<OutputViewProps> = ({
fileViewers,
editorOptions,
}) => {
const resolvedViewers = useMemo(
() => resolveViewers(viewers, fileViewers),
[fileViewers, viewers]
);

if (compilationState === undefined) {
return <></>;
}
if ("internalCompilerError" in compilationState) {
return <></>;
}
const resolvedViewers = useMemo(() => resolveViewers(viewers, fileViewers), [viewers]);
return (
<OutputViewInternal
compilationResult={compilationState}
Expand Down
16 changes: 11 additions & 5 deletions packages/playground/src/react/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export const Playground: FunctionComponent<PlaygroundProps> = (props) => {
);
useEffect(() => {
updateTypeSpec(props.defaultContent ?? "");
}, []);
}, [props.defaultContent, updateTypeSpec]);

useEffect(() => {
if (selectedSampleName && props.samples) {
Expand All @@ -174,7 +174,13 @@ export const Playground: FunctionComponent<PlaygroundProps> = (props) => {
}
}
}
}, [updateTypeSpec, selectedSampleName]);
}, [
updateTypeSpec,
selectedSampleName,
props.samples,
onSelectedEmitterChange,
onCompilerOptionsChange,
]);

useEffect(() => {
const debouncer = debounce(() => doCompile(), 200);
Expand Down Expand Up @@ -209,14 +215,14 @@ export const Playground: FunctionComponent<PlaygroundProps> = (props) => {

const formatCode = useCallback(() => {
void editorRef.current?.getAction("editor.action.formatDocument")?.run();
}, [typespecModel]);
}, []);

const fileBug = useCallback(async () => {
if (props.onFileBug) {
saveCode();
props.onFileBug();
}
}, [saveCode, typespecModel, props.onFileBug]);
}, [props, saveCode]);

const typespecEditorActions = useMemo(
(): editor.IActionDescriptor[] => [
Expand Down Expand Up @@ -251,7 +257,7 @@ export const Playground: FunctionComponent<PlaygroundProps> = (props) => {
(diagnostic: Diagnostic) => {
editorRef.current?.setSelection(getMonacoRange(host.compiler, diagnostic.target));
},
[setVerticalPaneSizes]
[host.compiler]
);

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/react/samples-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const SamplesDropdown: FunctionComponent<SamplesDropdownProps> = ({
onSelectedSampleNameChange(evt.target.value);
}
},
[onSelectedSampleNameChange]
[onSelectedSampleNameChange, samples]
);
return (
<Select
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/src/react/settings/compiler-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const CompilerSettings: FunctionComponent<CompilerSettingsProps> = ({
options: emitterOptions,
});
},
[options]
[onOptionsChanged, options]
);
const library = host.libraries[selectedEmitter];
const linterRuleSet = options.linterRuleSet ?? {};
Expand All @@ -37,7 +37,7 @@ export const CompilerSettings: FunctionComponent<CompilerSettingsProps> = ({
linterRuleSet,
});
},
[options]
[onOptionsChanged, options]
);
return (
<div>
Expand Down
17 changes: 9 additions & 8 deletions packages/playground/src/react/settings/emitter-options-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ export const EmitterOptionsForm: FunctionComponent<EmitterOptionsFormProps> = ({
options,
optionsChanged,
}) => {
const emitterOptionsSchema = library.definition?.emitter?.options?.properties;
if (emitterOptionsSchema === undefined) {
return <>"No options"</>;
}
const entries = Object.entries(emitterOptionsSchema);

const handleChange = useCallback(
({ name, value }: { name: string; value: unknown }) => {
optionsChanged({
Expand All @@ -41,8 +35,15 @@ export const EmitterOptionsForm: FunctionComponent<EmitterOptionsFormProps> = ({
},
});
},
[options, optionsChanged]
[library.name, options, optionsChanged]
);

const emitterOptionsSchema = library.definition?.emitter?.options?.properties;
if (emitterOptionsSchema === undefined) {
return <>"No options"</>;
}
const entries = Object.entries(emitterOptionsSchema);

return (
<div className={style["form"]}>
{entries.map(([key, value]) => {
Expand Down Expand Up @@ -90,7 +91,7 @@ const JsonSchemaPropertyInput: FunctionComponent<JsonSchemaPropertyInputProps> =
const handleChange = useCallback(
(_: unknown, data: RadioGroupOnChangeData | SwitchOnChangeData | InputOnChangeData) =>
onChange({ name, value: "value" in data ? data.value : data.checked }),
[onChange]
[name, onChange]
);

switch (prop.type) {
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/react/settings/linter-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const RuleSetCheckbox = ({ ruleSet, checked, onChange }: RuleSetCheckbox) => {
(_: any, data: CheckboxOnChangeData) => {
onChange(ruleSet, !!data.checked);
},
[ruleSet, checked, onChange]
[ruleSet, onChange]
);
return <Checkbox label={ruleSet} checked={checked} onChange={handleChange} />;
};
4 changes: 2 additions & 2 deletions packages/playground/src/react/standalone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function useStandalonePlaygroundContext(
setContext({ host, initialState, stateStorage });
};
void load();
}, []);
}, [config.importConfig, config.libraries]);
return context;
}

Expand Down Expand Up @@ -91,7 +91,7 @@ export const StandalonePlayground: FunctionComponent<ReactPlaygroundConfig> = (c
defaultCompilerOptions: context.initialState.options,
defaultSampleName: context.initialState.sampleName,
},
[context]
[config.defaultEmitter, config.libraries, context]
);
if (context === undefined || fixedOptions === undefined) {
return config.fallback;
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/react/typespec-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const OutputEditor: FunctionComponent<{
value: string;
editorOptions?: PlaygroundEditorsOptions;
}> = ({ filename, value, editorOptions }) => {
const model = useMonacoModel(filename);
if (filename === "") {
return null;
}
Expand All @@ -40,7 +41,6 @@ export const OutputEditor: FunctionComponent<{
enabled: false,
},
};
const model = useMonacoModel(filename);
model.setValue(value);
return <Editor model={model} options={options}></Editor>;
};
2 changes: 1 addition & 1 deletion packages/playground/src/react/viewers/react-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default (props: { spec: string }) => {
});
}
uiInstance.current.specActions.updateSpec(props.spec);
}, [uiRef.current, props.spec]);
}, [props.spec]);

return <div ref={uiRef}></div>;
};
6 changes: 3 additions & 3 deletions packages/react-components/src/split-pane/split-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ export const SplitPane: FunctionComponent<SplitPaneProps> = ({

return res;
},
[...resolvedPropSize, children.length, wrapSize]
[children, resolvedPropSize, wrapSize]
);

const sashPosSizes = useMemo(
() => sizes.reduce((a, b) => [...a, a[a.length - 1] + b], [0]),
[...sizes]
[sizes]
);

const dragStart = useCallback(
Expand Down Expand Up @@ -185,7 +185,7 @@ export const SplitPane: FunctionComponent<SplitPaneProps> = ({

updateSizes(nextSizes);
},
[paneLimitSizes, onChange]
[splitAxis, sizes, paneLimitSizes, updateSizes]
);

const paneFollow = !(performanceMode && isDragging);
Expand Down
Loading

0 comments on commit 4553419

Please sign in to comment.