From 6250d993ea1436edf85dd2df1a97acbe37081ce6 Mon Sep 17 00:00:00 2001 From: Raquel Amorim Date: Thu, 15 Sep 2022 12:36:10 -0400 Subject: [PATCH 1/5] enable rules --- packages/website/.eslintrc.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/website/.eslintrc.js b/packages/website/.eslintrc.js index 8b30fb624986..0b55f475b33c 100644 --- a/packages/website/.eslintrc.js +++ b/packages/website/.eslintrc.js @@ -22,7 +22,6 @@ module.exports = { 'react/jsx-no-target-blank': 'off', 'react/no-unescaped-entities': 'off', '@typescript-eslint/internal/prefer-ast-types-enum': 'off', - 'react-hooks/exhaustive-deps': 'off', // TODO: enable it later }, settings: { react: { From 0c70dca7985a034cdd709a36e9a763decbc38b4b Mon Sep 17 00:00:00 2001 From: Raquel Amorim Date: Thu, 15 Sep 2022 12:41:31 -0400 Subject: [PATCH 2/5] fix warnings --- .../website/src/components/ASTViewerTS.tsx | 12 ++- .../src/components/OptionsSelector.tsx | 4 +- .../website/src/components/Playground.tsx | 15 ++-- .../website/src/components/ast/Elements.tsx | 4 +- .../src/components/ast/PropertyName.tsx | 14 ++-- .../website/src/components/ast/SimpleItem.tsx | 2 +- .../src/components/config/ConfigEditor.tsx | 15 ++-- .../src/components/config/ConfigEslint.tsx | 21 +++--- .../components/config/ConfigTypeScript.tsx | 17 +++-- .../src/components/editor/LoadedEditor.tsx | 73 +++++++++++++++---- .../components/editor/useSandboxServices.ts | 5 +- .../components/hooks/useDebouncedToggle.ts | 2 +- .../src/components/inputs/Checkbox.tsx | 21 +++--- .../website/src/components/modals/Modal.tsx | 10 ++- 14 files changed, 141 insertions(+), 74 deletions(-) diff --git a/packages/website/src/components/ASTViewerTS.tsx b/packages/website/src/components/ASTViewerTS.tsx index 8cd3f15ce5a8..f198ef858c19 100644 --- a/packages/website/src/components/ASTViewerTS.tsx +++ b/packages/website/src/components/ASTViewerTS.tsx @@ -53,7 +53,17 @@ export default function ASTViewerTS({ ['TypeFlags', typeFlags], ); setModel(serialize(value, scopeSerializer)); - }, [value, syntaxKind]); + }, [ + value, + syntaxKind, + nodeFlags, + tokenFlags, + modifierFlags, + objectFlags, + symbolFlags, + flowFlags, + typeFlags, + ]); return ( diff --git a/packages/website/src/components/OptionsSelector.tsx b/packages/website/src/components/OptionsSelector.tsx index b9b78edfad09..505abc57031e 100644 --- a/packages/website/src/components/OptionsSelector.tsx +++ b/packages/website/src/components/OptionsSelector.tsx @@ -56,7 +56,7 @@ function OptionsSelectorContent({ .then(() => { setCopyLink(true); }); - }, []); + }, [setCopyLink]); const copyMarkdownToClipboard = useCallback(() => { if (isLoading) { @@ -65,7 +65,7 @@ function OptionsSelectorContent({ void navigator.clipboard.writeText(createMarkdown(state)).then(() => { setCopyMarkdown(true); }); - }, [state, isLoading]); + }, [isLoading, state, setCopyMarkdown]); const openIssue = useCallback(() => { if (isLoading) { diff --git a/packages/website/src/components/Playground.tsx b/packages/website/src/components/Playground.tsx index d86893bb56cd..e5833e888285 100644 --- a/packages/website/src/components/Playground.tsx +++ b/packages/website/src/components/Playground.tsx @@ -85,6 +85,15 @@ function Playground(): JSX.Element { [setState], ); + const onLoaded = useCallback( + (ruleNames: RuleDetails[], tsVersions: readonly string[]): void => { + setRuleNames(ruleNames); + setTSVersion(tsVersions); + setIsLoading(false); + }, + [], + ); + return (
{ruleNames.length > 0 && ( @@ -136,11 +145,7 @@ function Playground(): JSX.Element { onMarkersChange={setMarkers} decoration={selectedRange} onChange={setState} - onLoaded={(ruleNames, tsVersions): void => { - setRuleNames(ruleNames); - setTSVersion(tsVersions); - setIsLoading(false); - }} + onLoaded={onLoaded} onSelect={setPosition} />
diff --git a/packages/website/src/components/ast/Elements.tsx b/packages/website/src/components/ast/Elements.tsx index def515f54efd..25fbc0db857d 100644 --- a/packages/website/src/components/ast/Elements.tsx +++ b/packages/website/src/components/ast/Elements.tsx @@ -33,7 +33,7 @@ export function ComplexItem({ } } }, - [data], + [data.model.range, onSelectNode], ); useEffect(() => { @@ -50,7 +50,7 @@ export function ComplexItem({ if (selected && !isExpanded) { setIsExpanded(selected); } - }, [selection, data]); + }, [selection, data, level, isExpanded]); return ( ) => { e.preventDefault(); - props.onClick?.(e); + onClickProps?.(e); }, - [props.onClick], + [onClickProps], ); const onMouseEnter = useCallback(() => { - props.onHover?.(true); - }, [props.onHover]); + onHover?.(true); + }, [onHover]); const onMouseLeave = useCallback(() => { - props.onHover?.(false); - }, [props.onHover]); + onHover?.(false); + }, [onHover]); return props.onClick || props.onHover ? ( <> diff --git a/packages/website/src/components/ast/SimpleItem.tsx b/packages/website/src/components/ast/SimpleItem.tsx index c6e597dc8e9c..0b0a27ba1694 100644 --- a/packages/website/src/components/ast/SimpleItem.tsx +++ b/packages/website/src/components/ast/SimpleItem.tsx @@ -20,7 +20,7 @@ export function SimpleItem({ onSelectNode(state ? data.model.range : null); } }, - [data], + [data.model.range, onSelectNode], ); return ( diff --git a/packages/website/src/components/config/ConfigEditor.tsx b/packages/website/src/components/config/ConfigEditor.tsx index 4f0f9d939955..b074128a8b44 100644 --- a/packages/website/src/components/config/ConfigEditor.tsx +++ b/packages/website/src/components/config/ConfigEditor.tsx @@ -90,26 +90,27 @@ function isDefault(value: unknown, defaults?: unknown[]): boolean { } function ConfigEditor(props: ConfigEditorProps): JSX.Element { + const { onClose: onCloseProps, isOpen, values } = props; const [filter, setFilter] = useState(''); const [config, setConfig] = useReducer(reducerObject, {}); const [filterInput, setFilterFocus] = useFocus(); const onClose = useCallback(() => { - props.onClose(config); - }, [props.onClose, config]); + onCloseProps(config); + }, [onCloseProps, config]); useEffect(() => { - setConfig({ type: 'init', config: props.values }); - }, [props.values]); + setConfig({ type: 'init', config: values }); + }, [values]); useEffect(() => { - if (props.isOpen) { + if (isOpen) { setFilterFocus(); } - }, [props.isOpen]); + }, [isOpen, setFilterFocus]); return ( - +
([]); 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, @@ -51,7 +52,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, @@ -61,7 +62,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element { })), }, ]); - }, [props.ruleOptions]); + }, [ruleOptions]); const onClose = useCallback( (newConfig: Record) => { @@ -75,14 +76,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 ( @@ -90,7 +91,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 91a4781d14fe..1c29ae4f623a 100644 --- a/packages/website/src/components/config/ConfigTypeScript.tsx +++ b/packages/website/src/components/config/ConfigTypeScript.tsx @@ -12,14 +12,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) { @@ -53,20 +54,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 ( @@ -74,7 +75,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 65de546a25ad..c1b12528a8d9 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -83,7 +83,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'; @@ -100,7 +105,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( @@ -109,19 +120,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'); @@ -154,9 +165,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 @@ -230,7 +260,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); @@ -256,7 +299,7 @@ export const LoadedEditor: React.FC = ({ }, ]); } - }, [code]); + }, [code, tabs.code]); useEffect(() => { if (tsconfig !== tabs.tsconfig.getValue()) { @@ -267,7 +310,7 @@ export const LoadedEditor: React.FC = ({ }, ]); } - }, [tsconfig]); + }, [tabs.tsconfig, tsconfig]); useEffect(() => { if (eslintrc !== tabs.eslintrc.getValue()) { @@ -278,7 +321,7 @@ export const LoadedEditor: React.FC = ({ }, ]); } - }, [eslintrc]); + }, [eslintrc, tabs.eslintrc]); useEffect(() => { sandboxInstance.monaco.editor.setTheme(darkTheme ? 'vs-dark' : 'vs-light'); @@ -308,7 +351,7 @@ export const LoadedEditor: React.FC = ({ ), ); } - }, [decoration, sandboxInstance, showAST]); + }, [decoration, decorations, 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 c786e9996045..c20a8f5654d5 100644 --- a/packages/website/src/components/editor/useSandboxServices.ts +++ b/packages/website/src/components/editor/useSandboxServices.ts @@ -33,6 +33,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(); @@ -110,7 +111,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]), @@ -145,7 +146,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 73b655d28e79..537dbaee6209 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 ed5a473b1578..0134bfa40012 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 ( @@ -19,7 +21,7 @@ function Modal(props: ModalProps): JSX.Element { // eslint-disable-next-line deprecation/deprecation -- intentional fallback for old browsers e.keyCode === 27 ) { - props.onClose(); + onClose(); } }; @@ -27,15 +29,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 ( From 59b66ac748793f9537dff14855cf5b94c2fb2591 Mon Sep 17 00:00:00 2001 From: Raquel Amorim Date: Tue, 27 Sep 2022 16:32:36 -0400 Subject: [PATCH 3/5] add missing dependencies --- packages/website/src/components/editor/LoadedEditor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index 62a373d40b6b..81ef3db75c53 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -280,7 +280,7 @@ export const LoadedEditor: React.FC = ({ return new ResizeObserver(() => { resize(); }); - }, []); + }, [resize]); useEffect(() => { if (domNode) { @@ -289,7 +289,7 @@ export const LoadedEditor: React.FC = ({ return (): void => resizeObserver.unobserve(domNode); } return (): void => {}; - }, [domNode]); + }, [domNode, resizeObserver]); useEffect(() => { window.addEventListener('resize', resize); From c025a316b79d79c0632e98d75fe046fff6bc9c0f Mon Sep 17 00:00:00 2001 From: Raquel Amorim Date: Tue, 27 Sep 2022 20:59:57 -0400 Subject: [PATCH 4/5] fix infinite rerenders --- packages/website/src/components/editor/LoadedEditor.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index 81ef3db75c53..e641d77baa5a 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 = { @@ -337,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 ? [ { @@ -359,7 +360,7 @@ export const LoadedEditor: React.FC = ({ ), ); } - }, [decoration, decorations, sandboxInstance, showAST, tabs.code]); + }, [decoration, sandboxInstance, showAST, tabs.code]); return null; }; From 507c7a59bc5e2ca3ae88f879d71b5201bbd03060 Mon Sep 17 00:00:00 2001 From: Raquel Amorim Date: Tue, 27 Sep 2022 21:00:16 -0400 Subject: [PATCH 5/5] fix expansion of tree items --- packages/website/src/components/ast/Elements.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/ast/Elements.tsx b/packages/website/src/components/ast/Elements.tsx index a9476cc2d035..b8a9d7c823c6 100644 --- a/packages/website/src/components/ast/Elements.tsx +++ b/packages/website/src/components/ast/Elements.tsx @@ -44,10 +44,10 @@ export function ComplexItem({ level !== 'ast' && selected && !hasChildInRange(selection, data.model), ); - if (selected && !isExpanded) { + if (selected) { setIsExpanded(selected); } - }, [selection, data, level, isExpanded]); + }, [selection, data, level]); return ( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy