Add React hooks eslint

This commit is contained in:
Gregory Schier
2023-04-01 15:26:57 -07:00
parent 604254257d
commit b23e56c3af
23 changed files with 151 additions and 98 deletions

View File

@@ -54,7 +54,7 @@ export function Dropdown({ children, items }: DropdownProps) {
const handleClose = useCallback(() => {
setOpen(false);
ref.current?.focus();
}, [ref.current]);
}, []);
useEffect(() => {
ref.current?.setAttribute('aria-expanded', open.toString());
@@ -63,7 +63,7 @@ export function Dropdown({ children, items }: DropdownProps) {
const triggerRect = useMemo(() => {
if (!open) return null;
return ref.current?.getBoundingClientRect();
}, [ref.current, open]);
}, [open]);
return (
<>
@@ -83,8 +83,6 @@ interface MenuProps {
}
function Menu({ className, items, onClose, triggerRect }: MenuProps) {
if (triggerRect === undefined) return null;
const containerRef = useRef<HTMLDivElement | null>(null);
const [menuStyles, setMenuStyles] = useState<CSSProperties>({});

View File

@@ -88,12 +88,14 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
const { view, languageCompartment } = cm.current;
const ext = getLanguageExtension({ contentType, useTemplating, autocomplete });
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
}, [contentType, autocomplete]);
}, [contentType, autocomplete, useTemplating]);
useEffect(() => {
if (cm.current === null) return;
const { view } = cm.current;
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: defaultValue ?? '' } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [forceUpdateKey]);
// Initialize the editor when ref mounts
@@ -133,6 +135,8 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
} catch (e) {
console.log('Failed to initialize Codemirror', e);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const cmContainer = (

View File

@@ -36,7 +36,7 @@ const _IconButton = forwardRef<HTMLButtonElement, Props>(function IconButton(
if (showConfirm) setConfirmed();
onClick?.(e);
},
[onClick],
[onClick, setConfirmed, showConfirm],
);
return (
<Button

View File

@@ -63,10 +63,13 @@ export function Input({
return true;
}, [currentValue, validate, require]);
const handleChange = useCallback((value: string) => {
setCurrentValue(value);
onChange?.(value);
}, []);
const handleChange = useCallback(
(value: string) => {
setCurrentValue(value);
onChange?.(value);
},
[onChange],
);
return (
<VStack className="w-full">

View File

@@ -62,6 +62,8 @@ export const PairEditor = memo(function PairEditor({
const nonEmpty = originalPairs.filter((h) => !(h.name === '' && h.value === ''));
const pairs = nonEmpty.map((pair) => newPairContainer(pair));
setPairs([...pairs, newPairContainer()]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [forceUpdateKey]);
const setPairsAndSave = useCallback(
@@ -99,19 +101,19 @@ export const PairEditor = memo(function PairEditor({
return newPairs;
});
},
[hoveredIndex],
[hoveredIndex, setPairsAndSave],
);
const handleChange = useCallback(
(pair: PairContainer) =>
setPairsAndSave((pairs) => pairs.map((p) => (pair.id !== p.id ? p : pair))),
[],
[setPairsAndSave],
);
const handleDelete = useCallback(
(pair: PairContainer) =>
setPairsAndSave((oldPairs) => oldPairs.filter((p) => p.id !== pair.id)),
[],
[setPairsAndSave],
);
const handleFocus = useCallback(
@@ -216,17 +218,17 @@ const FormRow = memo(function FormRow({
const handleChangeEnabled = useMemo(
() => (enabled: boolean) => onChange({ id, pair: { ...pairContainer.pair, enabled } }),
[onChange, pairContainer.pair.name, pairContainer.pair.value],
[id, onChange, pairContainer.pair],
);
const handleChangeName = useMemo(
() => (name: string) => onChange({ id, pair: { ...pairContainer.pair, name } }),
[onChange, pairContainer.pair.value, pairContainer.pair.enabled],
[onChange, id, pairContainer.pair],
);
const handleChangeValue = useMemo(
() => (value: string) => onChange({ id, pair: { ...pairContainer.pair, value } }),
[onChange, pairContainer.pair.name, pairContainer.pair.enabled],
[onChange, id, pairContainer.pair],
);
const handleFocus = useCallback(() => onFocus?.(pairContainer), [onFocus, pairContainer]);

View File

@@ -39,7 +39,7 @@ export function RadioDropdown<T = string | null>({
};
}
}),
[value, items],
[items, value, onChange],
);
return <Dropdown items={dropdownItems}>{children}</Dropdown>;

View File

@@ -1,6 +1,6 @@
import classnames from 'classnames';
import type { ReactNode } from 'react';
import { memo, useEffect, useRef } from 'react';
import { memo, useCallback, useEffect, useRef } from 'react';
import { Button } from '../Button';
import { Icon } from '../Icon';
import type { RadioDropdownProps } from '../RadioDropdown';
@@ -38,28 +38,31 @@ export function Tabs({
}: Props) {
const ref = useRef<HTMLDivElement | null>(null);
const handleTabChange = (value: string) => {
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab');
if (v === value) {
tab.setAttribute('tabindex', '-1');
tab.setAttribute('data-state', 'active');
tab.setAttribute('aria-hidden', 'false');
tab.style.display = 'block';
} else {
tab.setAttribute('data-state', 'inactive');
tab.setAttribute('aria-hidden', 'true');
tab.style.display = 'none';
const handleTabChange = useCallback(
(value: string) => {
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab');
if (v === value) {
tab.setAttribute('tabindex', '-1');
tab.setAttribute('data-state', 'active');
tab.setAttribute('aria-hidden', 'false');
tab.style.display = 'block';
} else {
tab.setAttribute('data-state', 'inactive');
tab.setAttribute('aria-hidden', 'true');
tab.style.display = 'none';
}
}
}
onChangeValue(value);
};
onChangeValue(value);
},
[onChangeValue],
);
useEffect(() => {
if (value === undefined) return;
handleTabChange(value);
}, [value]);
}, [handleTabChange, value]);
return (
<div

View File

@@ -13,7 +13,7 @@ export function Webview({ body, url, contentType }: Props) {
return body.replace(/<head>/gi, `<head><base href="${url}"/>`);
}
return body;
}, [body, contentType]);
}, [url, body, contentType]);
return (
<div className="px-2 pb-2">