fix: Restore some react-hook lint rules (#2084)

## Summary

This PR:

- Updates the eslint config to restore `react-hook` plugin rules which were removed in #2069. Some of them were removed in without any replacements being _enabled_ in the recommended @eslint-react ruleset
- Reverts #2074, as those lint fixes were possible only because the related rules had been removed

Rule equivalence is documented here: https://www.eslint-react.xyz/docs/migrating-from-eslint-plugin-react-hooks

You can view current effective rule states with `cd packages/app && npx eslint --inspect-config`

### How to test locally or on Vercel

Locally:

```
make ci-lint / make dev-lint
```

### References



- Linear Issue: HDX-3467
- Related PRs:
This commit is contained in:
Drew Davis 2026-04-09 15:08:23 -04:00 committed by GitHub
parent 61db3e8b43
commit 5de23e1988
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 31 additions and 9 deletions

View file

@ -122,12 +122,28 @@ export default [
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
...reactHooksPlugin.configs.recommended.rules,
...eslintReactPlugin.configs.recommended.rules,
// Disable rules from eslint-plugin-react-hooks that have equivalent rules in @eslint-react
...eslintReactPlugin.configs['disable-conflict-eslint-plugin-react-hooks'].rules,
...eslintReactPlugin.configs['recommended-type-checked'].rules,
// Non-default react-hooks rules
'react-hooks/set-state-in-render': 'error',
'react-hooks/set-state-in-effect': 'warn',
'react-hooks/exhaustive-deps': 'error',
// Disable rules from @eslint-react that have equivalent rules enabled in eslint-plugin-react-hooks
'@eslint-react/rules-of-hooks': 'off',
'@eslint-react/component-hook-factories': 'off',
'@eslint-react/exhaustive-deps': 'off',
'@eslint-react/error-boundaries': 'off',
'@eslint-react/immutability': 'off',
'@eslint-react/purity': 'off',
'@eslint-react/refs': 'off',
'@eslint-react/set-state-in-effect': 'off',
'@eslint-react/set-state-in-render': 'off',
'@eslint-react/no-nested-component-definitions': 'off',
'@eslint-react/no-nested-lazy-component-declarations': 'off',
'@eslint-react/unsupported-syntax': 'off',
'@eslint-react/use-memo': 'off',
'react-hook-form/no-use-watch': 'error',
'@eslint-react/no-unstable-default-props': 'error',
'@typescript-eslint/ban-ts-comment': 'warn',

View file

@ -166,6 +166,7 @@ function AIAssistant({
</Group>
<Collapse in={opened}>
{opened && (
// eslint-disable-next-line react-hooks/refs
<form onSubmit={handleSubmit(onSubmit)}>
<Group mb="md">
<SourceSelectControlled

View file

@ -264,6 +264,7 @@ export default function DOMPlayer({
);
}
// eslint-disable-next-line react-hooks/immutability
updatePlayerTimeRafRef.current = requestAnimationFrame(updatePlayerTime);
}, []);

View file

@ -953,7 +953,7 @@ function Heatmap({
},
plugins: [
// legendAsTooltipPlugin()
// eslint-disable-next-line react-hooks/refs -- mouseInsideRef is read at event time, not during render
highlightDataPlugin({
proximity: 20,
yFormatter: tickFormatter,

View file

@ -98,7 +98,7 @@ export default function SQLEditor({
minHeight={'100px'}
extensions={[
createCodeMirrorStyleTheme(),
// eslint-disable-next-line react-hooks/refs
compartmentRef.current.of(
clickhouseSql({
upperCaseKeywords: true,

View file

@ -242,6 +242,7 @@ export default function SQLInlineEditor({
// Enable line wrapping when multiline is allowed (regardless of focus)
...(allowMultiline ? [EditorView.lineWrapping] : []),
// eslint-disable-next-line react-hooks/refs
compartmentRef.current.of(
clickhouseSql({
upperCaseKeywords: true,

View file

@ -52,7 +52,7 @@ function useResizable(
const endResize = useCallback(() => {
document.removeEventListener('mousemove', handleResize);
// eslint-disable-next-line react-hooks/immutability
document.removeEventListener('mouseup', endResize);
}, [handleResize]);

View file

@ -10,7 +10,7 @@ export const useStableCallback = <T extends (...args: any[]) => any>(
});
return useCallback(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
// eslint-disable-next-line react-hooks/use-memo, @typescript-eslint/no-unsafe-type-assertion
((...args: Parameters<T>) => callbackRef.current(...args)) as T,
[],
);

View file

@ -243,12 +243,13 @@ export function useTimeQuery({
liveTailTimeRange == null &&
tempLiveTailTimeRange == null &&
!isInputTimeQueryLive(inputTimeQuery) &&
// eslint-disable-next-line react-hooks/refs
inputTimeQueryDerivedTimeQueryRef.current != null
) {
// Use the input time query, allows users to specify relative time ranges
// via url ex. /logs?tq=Last+30+minutes
// return inputTimeQueryDerivedTimeQuery as [Date, Date];
// eslint-disable-next-line react-hooks/refs
return inputTimeQueryDerivedTimeQueryRef.current;
} else if (
isReady &&
@ -344,6 +345,7 @@ export function useTimeQuery({
],
);
// eslint-disable-next-line react-hooks/refs
return {
isReady, // Don't search until we know what we want to do
isLive,

View file

@ -28,6 +28,7 @@ export const QueryParamProvider = ({
const setState = useCallback(
(state: Record<string, any>) => {
// eslint-disable-next-line react-hooks/immutability
setCache(oldCache => {
const newCache = {
...oldCache,

View file

@ -643,7 +643,7 @@ export const usePrevious = <T>(value: T): T | undefined => {
useEffect(() => {
ref.current = value;
});
// eslint-disable-next-line react-hooks/refs
return ref.current;
};