([]);
const [configObject, updateConfigObject] = useState();
useEffect(() => {
- if (props.isOpen) {
- updateConfigObject(parseESLintRC(props.config));
+ if (isOpen) {
+ updateConfigObject(parseESLintRC(config));
}
- }, [props.isOpen, props.config]);
+ }, [isOpen, config]);
useEffect(() => {
updateOptions([
{
heading: 'Rules',
- fields: props.ruleOptions
+ fields: ruleOptions
.filter(item => item.name.startsWith('@typescript'))
.map(item => ({
key: item.name,
@@ -52,7 +53,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element {
},
{
heading: 'Core rules',
- fields: props.ruleOptions
+ fields: ruleOptions
.filter(item => !item.name.startsWith('@typescript'))
.map(item => ({
key: item.name,
@@ -62,7 +63,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element {
})),
},
]);
- }, [props.ruleOptions]);
+ }, [ruleOptions]);
const onClose = useCallback(
(newConfig: Record) => {
@@ -76,14 +77,14 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element {
.filter(checkOptions),
);
if (!shallowEqual(cfg, configObject?.rules)) {
- props.onClose({
+ onCloseProps({
eslintrc: toJson({ ...(configObject ?? {}), rules: cfg }),
});
} else {
- props.onClose();
+ onCloseProps();
}
},
- [props.onClose, configObject],
+ [onCloseProps, configObject],
);
return (
@@ -91,7 +92,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element {
header="Eslint Config"
options={options}
values={configObject?.rules ?? {}}
- isOpen={props.isOpen}
+ isOpen={isOpen}
onClose={onClose}
/>
);
diff --git a/packages/website/src/components/config/ConfigTypeScript.tsx b/packages/website/src/components/config/ConfigTypeScript.tsx
index 78cccd9e9e6..40cd634ffb1 100644
--- a/packages/website/src/components/config/ConfigTypeScript.tsx
+++ b/packages/website/src/components/config/ConfigTypeScript.tsx
@@ -13,14 +13,15 @@ interface ConfigTypeScriptProps {
}
function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element {
+ const { onClose: onCloseProps, isOpen, config } = props;
const [tsConfigOptions, updateOptions] = useState([]);
const [configObject, updateConfigObject] = useState();
useEffect(() => {
- if (props.isOpen) {
- updateConfigObject(parseTSConfig(props.config));
+ if (isOpen) {
+ updateConfigObject(parseTSConfig(config));
}
- }, [props.isOpen, props.config]);
+ }, [isOpen, config]);
useEffect(() => {
if (window.ts) {
@@ -54,20 +55,20 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element {
),
);
}
- }, [props.isOpen]);
+ }, [isOpen]);
const onClose = useCallback(
(newConfig: Record) => {
const cfg = { ...newConfig };
if (!shallowEqual(cfg, configObject?.compilerOptions)) {
- props.onClose({
+ onCloseProps({
tsconfig: toJson({ ...(configObject ?? {}), compilerOptions: cfg }),
});
} else {
- props.onClose();
+ onCloseProps();
}
},
- [props.onClose, configObject],
+ [onCloseProps, configObject],
);
return (
@@ -75,7 +76,7 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element {
header="TypeScript Config"
options={tsConfigOptions}
values={configObject?.compilerOptions ?? {}}
- isOpen={props.isOpen}
+ isOpen={isOpen}
onClose={onClose}
/>
);
diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx
index 3b959580193..e641d77baa5 100644
--- a/packages/website/src/components/editor/LoadedEditor.tsx
+++ b/packages/website/src/components/editor/LoadedEditor.tsx
@@ -47,7 +47,8 @@ export const LoadedEditor: React.FC = ({
webLinter,
activeTab,
}) => {
- const [decorations, setDecorations] = useState([]);
+ const [_, setDecorations] = useState([]);
+
const codeActions = useRef(new Map()).current;
const [tabs] = useState>(() => {
const tabsDefault = {
@@ -75,7 +76,12 @@ export const LoadedEditor: React.FC = ({
resource: model.uri,
});
onMarkersChange(parseMarkers(markers, codeActions, sandboxInstance.editor));
- }, []);
+ }, [
+ codeActions,
+ onMarkersChange,
+ sandboxInstance.editor,
+ sandboxInstance.monaco.editor,
+ ]);
useEffect(() => {
const newPath = jsx ? '/input.tsx' : '/input.ts';
@@ -92,7 +98,13 @@ export const LoadedEditor: React.FC = ({
tabs.code.dispose();
tabs.code = newModel;
}
- }, [jsx]);
+ }, [
+ jsx,
+ sandboxInstance.editor,
+ sandboxInstance.monaco.Uri,
+ sandboxInstance.monaco.editor,
+ tabs,
+ ]);
useEffect(() => {
const config = createCompilerOptions(
@@ -101,19 +113,19 @@ export const LoadedEditor: React.FC = ({
);
webLinter.updateCompilerOptions(config);
sandboxInstance.setCompilerSettings(config);
- }, [jsx, tsconfig]);
+ }, [jsx, sandboxInstance, tsconfig, webLinter]);
useEffect(() => {
webLinter.updateRules(parseESLintRC(eslintrc).rules);
- }, [eslintrc]);
+ }, [eslintrc, webLinter]);
useEffect(() => {
sandboxInstance.editor.setModel(tabs[activeTab]);
updateMarkers();
- }, [activeTab]);
+ }, [activeTab, sandboxInstance.editor, tabs, updateMarkers]);
- useEffect(
- debounce(() => {
+ useEffect(() => {
+ const lintEditor = debounce(() => {
// eslint-disable-next-line no-console
console.info('[Editor] linting triggered');
@@ -146,9 +158,28 @@ export const LoadedEditor: React.FC = ({
onTsASTChange(webLinter.storedTsAST);
onScopeChange(webLinter.storedScope);
onSelect(sandboxInstance.editor.getPosition());
- }, 500),
- [code, jsx, tsconfig, eslintrc, sourceType, webLinter],
- );
+ }, 500);
+
+ lintEditor();
+ }, [
+ code,
+ jsx,
+ tsconfig,
+ eslintrc,
+ sourceType,
+ webLinter,
+ onEsASTChange,
+ onTsASTChange,
+ onScopeChange,
+ onSelect,
+ sandboxInstance.editor,
+ sandboxInstance.monaco.editor,
+ sandboxInstance.monaco.Uri,
+ codeActions,
+ tabs.code,
+ updateMarkers,
+ onMarkersChange,
+ ]);
useEffect(() => {
// configure the JSON language support with schemas and schema associations
@@ -222,7 +253,20 @@ export const LoadedEditor: React.FC = ({
}
}
};
- }, []);
+ }, [
+ codeActions,
+ main.languages,
+ onChange,
+ onSelect,
+ sandboxInstance.editor,
+ sandboxInstance.monaco.editor,
+ sandboxInstance.monaco.languages.json.jsonDefaults,
+ tabs.code,
+ tabs.eslintrc,
+ tabs.tsconfig,
+ updateMarkers,
+ webLinter.ruleNames,
+ ]);
const resize = useMemo(() => {
return debounce(() => sandboxInstance.editor.layout(), 1);
@@ -237,7 +281,7 @@ export const LoadedEditor: React.FC = ({
return new ResizeObserver(() => {
resize();
});
- }, []);
+ }, [resize]);
useEffect(() => {
if (domNode) {
@@ -246,7 +290,7 @@ export const LoadedEditor: React.FC = ({
return (): void => resizeObserver.unobserve(domNode);
}
return (): void => {};
- }, [domNode]);
+ }, [domNode, resizeObserver]);
useEffect(() => {
window.addEventListener('resize', resize);
@@ -264,7 +308,7 @@ export const LoadedEditor: React.FC = ({
},
]);
}
- }, [code]);
+ }, [code, tabs.code]);
useEffect(() => {
if (tsconfig !== tabs.tsconfig.getValue()) {
@@ -275,7 +319,7 @@ export const LoadedEditor: React.FC = ({
},
]);
}
- }, [tsconfig]);
+ }, [tabs.tsconfig, tsconfig]);
useEffect(() => {
if (eslintrc !== tabs.eslintrc.getValue()) {
@@ -286,7 +330,7 @@ export const LoadedEditor: React.FC = ({
},
]);
}
- }, [eslintrc]);
+ }, [eslintrc, tabs.eslintrc]);
useEffect(() => {
sandboxInstance.monaco.editor.setTheme(darkTheme ? 'vs-dark' : 'vs-light');
@@ -294,9 +338,9 @@ export const LoadedEditor: React.FC = ({
useEffect(() => {
if (sandboxInstance.editor.getModel() === tabs.code) {
- setDecorations(
+ setDecorations(prevDecorations =>
sandboxInstance.editor.deltaDecorations(
- decorations,
+ prevDecorations,
decoration && showAST
? [
{
@@ -316,7 +360,7 @@ export const LoadedEditor: React.FC = ({
),
);
}
- }, [decoration, sandboxInstance, showAST]);
+ }, [decoration, sandboxInstance, showAST, tabs.code]);
return null;
};
diff --git a/packages/website/src/components/editor/useSandboxServices.ts b/packages/website/src/components/editor/useSandboxServices.ts
index d316f75acf9..73c336676b3 100644
--- a/packages/website/src/components/editor/useSandboxServices.ts
+++ b/packages/website/src/components/editor/useSandboxServices.ts
@@ -32,6 +32,7 @@ export interface SandboxServices {
export const useSandboxServices = (
props: SandboxServicesProps,
): Error | SandboxServices | undefined => {
+ const { onLoaded } = props;
const [services, setServices] = useState();
const [loadedTs, setLoadedTs] = useState(props.ts);
const { colorMode } = useColorMode();
@@ -109,7 +110,7 @@ export const useSandboxServices = (
const webLinter = new WebLinter(system, compilerOptions, lintUtils);
- props.onLoaded(
+ onLoaded(
webLinter.ruleNames,
Array.from(
new Set([...sandboxInstance.supportedVersions, window.ts.version]),
@@ -144,7 +145,7 @@ export const useSandboxServices = (
model.dispose();
}
};
- }, [props.ts]);
+ }, [props.ts, colorMode, props.jsx, onLoaded]);
return services;
};
diff --git a/packages/website/src/components/hooks/useDebouncedToggle.ts b/packages/website/src/components/hooks/useDebouncedToggle.ts
index b34bb889b0a..d857f4aea2c 100644
--- a/packages/website/src/components/hooks/useDebouncedToggle.ts
+++ b/packages/website/src/components/hooks/useDebouncedToggle.ts
@@ -19,7 +19,7 @@ export default function useDebouncedToggle(
setState(value);
}, timeout);
},
- [timeoutIdRef],
+ [timeout, value],
);
return [state, update];
diff --git a/packages/website/src/components/inputs/Checkbox.tsx b/packages/website/src/components/inputs/Checkbox.tsx
index ed5a473b157..0134bfa4001 100644
--- a/packages/website/src/components/inputs/Checkbox.tsx
+++ b/packages/website/src/components/inputs/Checkbox.tsx
@@ -1,4 +1,4 @@
-import React, { createRef, useEffect } from 'react';
+import React, { useCallback } from 'react';
export interface CheckboxProps {
readonly name: string;
@@ -10,17 +10,18 @@ export interface CheckboxProps {
}
function Checkbox(props: CheckboxProps): JSX.Element {
- const checkboxRef = createRef();
+ const { indeterminate } = props;
- useEffect(() => {
- if (!checkboxRef.current) {
- return;
- }
+ const checkboxRef = useCallback(
+ (node: HTMLInputElement | null) => {
+ if (!node) {
+ return;
+ }
- if (props.indeterminate !== checkboxRef.current.indeterminate) {
- checkboxRef.current.indeterminate = props.indeterminate ?? false;
- }
- }, [props.indeterminate]);
+ node.indeterminate = indeterminate ?? false;
+ },
+ [indeterminate],
+ );
return (
{
const closeOnEscapeKeyDown = (e: KeyboardEvent): void => {
if (
@@ -21,7 +23,7 @@ function Modal(props: ModalProps): JSX.Element {
// eslint-disable-next-line deprecation/deprecation -- intentional fallback for old browsers
e.keyCode === 27
) {
- props.onClose();
+ onClose();
}
};
@@ -29,15 +31,15 @@ function Modal(props: ModalProps): JSX.Element {
return (): void => {
document.body.removeEventListener('keydown', closeOnEscapeKeyDown);
};
- }, []);
+ }, [onClose]);
const onClick = useCallback(
(e: MouseEvent) => {
if (e.currentTarget === e.target) {
- props.onClose();
+ onClose();
}
},
- [props.onClose],
+ [onClose],
);
return (