From 08968311865d0318e81351971b7fb42c9460ce97 Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Wed, 13 May 2026 18:22:13 -0400 Subject: [PATCH] feat: don't allow importing react --- web/eslint.config.ts | 15 +++++++++++++++ web/src/components/topology/Korrel8rTopology.tsx | 4 ++-- web/src/hooks/useAgentNavigation.ts | 10 +++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/web/eslint.config.ts b/web/eslint.config.ts index edc108e..4292a6b 100644 --- a/web/eslint.config.ts +++ b/web/eslint.config.ts @@ -78,6 +78,21 @@ export default defineConfig([ 'react-hooks/set-state-in-render': 'off', 'react-hooks/incompatible-library': 'off', '@typescript-eslint/no-explicit-any': 'off', + + // Prevent directly importing react as a lint rule + 'no-restricted-syntax': [ + 'error', + { + selector: 'ImportDeclaration[source.value="react"] ImportDefaultSpecifier', + message: + 'Do not directly import React. Add specific named imports instead (`import { useState, FC } from "react"`).', + }, + { + selector: 'ImportDeclaration[source.value="react"] ImportNamespaceSpecifier', + message: + 'Do not directly namespace import React (`import * as React`). Add specific named imports instead (`import { useState, FC } from "react"`).', + }, + ], }, }, { diff --git a/web/src/components/topology/Korrel8rTopology.tsx b/web/src/components/topology/Korrel8rTopology.tsx index f36066a..16f4931 100644 --- a/web/src/components/topology/Korrel8rTopology.tsx +++ b/web/src/components/topology/Korrel8rTopology.tsx @@ -38,7 +38,7 @@ import { useNavigateToQuery } from '../../hooks/useNavigateToQuery'; import * as korrel8r from '../../korrel8r/types'; import { getIcon } from '../icons'; import './korrel8rtopology.css'; -import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { FC, ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react'; // DagreLayout with straight edges (no angular bendpoints). class StraightEdgeDagreLayout extends DagreLayout { @@ -157,7 +157,7 @@ export const Korrel8rTopology: FC<{ ); const nodeMenu = useCallback( - (e: GraphElement): React.ReactElement[] => { + (e: GraphElement): ReactElement[] => { const node = e.getData(); const menu = [ diff --git a/web/src/hooks/useAgentNavigation.ts b/web/src/hooks/useAgentNavigation.ts index 898ee7f..53bc7f2 100644 --- a/web/src/hooks/useAgentNavigation.ts +++ b/web/src/hooks/useAgentNavigation.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useEffect, useRef } from 'react'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { getConsoleUpdates, sendConsoleUpdate } from '../korrel8r-client'; import * as api from '../korrel8r/client'; @@ -27,13 +27,13 @@ const useAgentNavigation = ({ const dispatch = useDispatch(); const navigateToQuery = useNavigateToQuery(); - const navigateToQueryRef = React.useRef(navigateToQuery); - React.useEffect(() => { + const navigateToQueryRef = useRef(navigateToQuery); + useEffect(() => { navigateToQueryRef.current = navigateToQuery; }); // Handle console update events via an SSE request. - React.useEffect(() => { + useEffect(() => { if (!agentEnabled) { dispatch(setAgentError('')); return; @@ -68,7 +68,7 @@ const useAgentNavigation = ({ }, [agentEnabled, minDelay, maxDelay, dispatch]); // Send console updates when view or search changes. - React.useEffect(() => { + useEffect(() => { if (!agentEnabled) return; const body = { view,