Skip to content

Commit

Permalink
feat: implement new linter rules in preparation for react compiler
Browse files Browse the repository at this point in the history
- All code logic should be identical
- did some swapping out of refs for state vars to improve adherence to the rules of react
  • Loading branch information
ryanhopperlowe committed Dec 18, 2024
1 parent 3965091 commit 8d9bcba
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 39 deletions.
3 changes: 2 additions & 1 deletion ui/admin/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = {
// React
{
files: ["**/*.{js,jsx,ts,tsx}"],
plugins: ["react", "jsx-a11y"],
plugins: ["react", "jsx-a11y", "react-compiler"],
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
Expand All @@ -50,6 +50,7 @@ module.exports = {
},
rules: {
"react/prop-types": "off",
"react-compiler/react-compiler": "error",
"no-restricted-imports": [
"error",
{
Expand Down
21 changes: 17 additions & 4 deletions ui/admin/app/components/ui/multi-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ const CommandEmpty = forwardRef<

CommandEmpty.displayName = "CommandEmpty";

/**
* @deprecated This component is super bulky and has some weird bugs. We need to create a new one that behaves similarly to ComboBox
*/
const MultiSelect = React.forwardRef<MultiSelectRef, MultiSelectProps>(
(
{
Expand Down Expand Up @@ -334,8 +337,13 @@ const MultiSelect = React.forwardRef<MultiSelectRef, MultiSelectProps>(
};

void exec();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedSearchTerm, groupBy, open, triggerSearchOnFocus]);
}, [
debouncedSearchTerm,
groupBy,
open,
triggerSearchOnFocus,
onSearchSync,
]);

useEffect(() => {
/** async search */
Expand All @@ -360,8 +368,13 @@ const MultiSelect = React.forwardRef<MultiSelectRef, MultiSelectProps>(
};

void exec();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedSearchTerm, groupBy, open, triggerSearchOnFocus]);
}, [
debouncedSearchTerm,
groupBy,
open,
triggerSearchOnFocus,
onSearch,
]);

const CreatableItem = () => {
if (!creatable) return undefined;
Expand Down
12 changes: 10 additions & 2 deletions ui/admin/app/components/ui/scroll-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const ScrollArea = React.forwardRef<
...rootProps
} = props;

const [viewportEl, setViewportEl] = React.useState<HTMLDivElement | null>(
null
);
const viewportRef = React.useRef<HTMLDivElement | null>(null);
const [shouldStickToBottom, setShouldStickToBottom] = React.useState(
enableScrollStick === "bottom"
Expand All @@ -49,6 +52,11 @@ const ScrollArea = React.forwardRef<
}
}, [enableScrollStick, shouldStickToBottom, children]);

const initRef = React.useCallback((node: HTMLDivElement | null) => {
setViewportEl(node);
viewportRef.current = node;
}, []);

return (
<ScrollAreaPrimitive.Root
ref={ref}
Expand All @@ -57,7 +65,7 @@ const ScrollArea = React.forwardRef<
>
<ScrollAreaPrimitive.Viewport
className="h-full w-full rounded-[inherit] max-h-[inherit]"
ref={viewportRef}
ref={initRef}
onScroll={(e) =>
setShouldStickToBottom(isScrolledToBottom(e.currentTarget))
}
Expand All @@ -66,7 +74,7 @@ const ScrollArea = React.forwardRef<
{enableScrollTo === "bottom" && (
<ScrollToBottom
onClick={() => setShouldStickToBottom(true)}
scrollContainerEl={viewportRef.current}
scrollContainerEl={viewportEl}
disabled={shouldStickToBottom}
/>
)}
Expand Down
7 changes: 2 additions & 5 deletions ui/admin/app/components/ui/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
} from "~/components/ui/tooltip";
import { useIsMobile } from "~/hooks/use-mobile";

const SIDEBAR_COOKIE_NAME = "sidebar:state";
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
const _SIDEBAR_COOKIE_NAME = "sidebar:state";
const _SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
const SIDEBAR_WIDTH = "13rem";
const SIDEBAR_WIDTH_MOBILE = "18rem";
const SIDEBAR_WIDTH_ICON = "3rem";
Expand Down Expand Up @@ -81,9 +81,6 @@ const SidebarProvider = React.forwardRef<
}

_setOpen(value);

// This sets the cookie to keep the sidebar state.
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
},
[setOpenProp, open]
);
Expand Down
38 changes: 19 additions & 19 deletions ui/admin/app/components/ui/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ const useAutosizeTextArea = ({
setInit(false);
}

node.style.height = `${
Math.min(Math.max(node.scrollHeight, minHeight), maxHeight) +
offsetBorder
}px`;
const newHeight = Math.min(
Math.max(node.scrollHeight, minHeight + offsetBorder),
maxHeight + offsetBorder
);

node.style.height = `${newHeight}px`;
},
// disable exhaustive deps because we don't want to rerun this after init is set to false
// eslint-disable-next-line react-hooks/exhaustive-deps
[maxHeight, minHeight]
[maxHeight, minHeight, setInit, init]
);

const initResizer = React.useCallback(
Expand All @@ -145,6 +145,7 @@ const useAutosizeTextArea = ({
node.oninput = () => resize(node);
node.onresize = () => resize(node);
node.onchange = () => resize(node);

resize(node);
},
[resize]
Expand All @@ -153,15 +154,14 @@ const useAutosizeTextArea = ({
React.useEffect(() => {
if (textAreaRef) {
initResizer(textAreaRef);
resize(textAreaRef);
}
}, [resize, initResizer, textAreaRef]);
}, [initResizer, textAreaRef]);

return { initResizer };
};

export type AutosizeTextAreaRef = {
textArea: HTMLTextAreaElement;
textArea: HTMLTextAreaElement | null;
maxHeight: number;
minHeight: number;
};
Expand All @@ -185,35 +185,35 @@ const AutosizeTextarea = React.forwardRef<
}: AutosizeTextAreaProps,
ref: React.Ref<AutosizeTextAreaRef>
) => {
const textAreaRef = React.useRef<HTMLTextAreaElement | null>(null);
const [textAreaEl, setTextAreaEl] =
React.useState<HTMLTextAreaElement | null>(null);

useImperativeHandle(ref, () => ({
textArea: textAreaRef.current as HTMLTextAreaElement,
focus: textAreaRef?.current?.focus,
textArea: textAreaEl,
focus: textAreaEl?.focus,
maxHeight,
minHeight,
}));

const { initResizer } = useAutosizeTextArea({
textAreaRef: textAreaRef.current,
textAreaRef: textAreaEl,
maxHeight,
minHeight,
});

const initRef = React.useCallback(
(node: HTMLTextAreaElement | null) => {
textAreaRef.current = node;

if (!node) return;
setTextAreaEl(node);

initResizer(node);
if (node) initResizer(node);
},
[initResizer]
);

return (
<Textarea
{...props}
rows={props.rows || 1}
ref={initRef}
className={cn("resize-none", className)}
onChange={onChange}
Expand All @@ -223,4 +223,4 @@ const AutosizeTextarea = React.forwardRef<
);
AutosizeTextarea.displayName = "AutosizeTextarea";

export { Textarea, AutosizeTextarea, useAutosizeTextArea };
export { AutosizeTextarea, Textarea, useAutosizeTextArea };
8 changes: 0 additions & 8 deletions ui/admin/app/hooks/useLogEffect.ts

This file was deleted.

1 change: 1 addition & 0 deletions ui/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.36.1",
"eslint-plugin-react-compiler": "19.0.0-beta-201e55d-20241215",
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.38",
"prettier": "^3.3.3",
Expand Down
58 changes: 58 additions & 0 deletions ui/admin/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d9bcba

Please sign in to comment.