diff --git a/kafka-ui-react-app/.eslintrc.json b/kafka-ui-react-app/.eslintrc.json index 14cb601fde..414474c3db 100644 --- a/kafka-ui-react-app/.eslintrc.json +++ b/kafka-ui-react-app/.eslintrc.json @@ -22,7 +22,8 @@ }, "plugins": [ "@typescript-eslint", - "prettier" + "prettier", + "eslint-plugin-react-hooks" ], "extends": [ "airbnb", @@ -33,6 +34,8 @@ "prettier" ], "rules": { + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "warn", "react/no-unused-prop-types": "off", "react/require-default-props": "off", "prettier/prettier": "warn", diff --git a/kafka-ui-react-app/src/components/Alerts/Alerts.tsx b/kafka-ui-react-app/src/components/Alerts/Alerts.tsx index 23bdb300b9..8dcbf6cdac 100644 --- a/kafka-ui-react-app/src/components/Alerts/Alerts.tsx +++ b/kafka-ui-react-app/src/components/Alerts/Alerts.tsx @@ -8,14 +8,20 @@ import Alert from 'components/Alerts/Alert'; const Alerts: React.FC = () => { const alerts = useAppSelector(selectAll); const dispatch = useAppDispatch(); - const dismiss = React.useCallback((id: string) => { - dispatch(alertDissmissed(id)); - }, []); + const dismiss = React.useCallback( + (id: string) => { + dispatch(alertDissmissed(id)); + }, + [dispatch] + ); const legacyAlerts = useAppSelector(getAlerts); - const dismissLegacy = React.useCallback((id: string) => { - dispatch(dismissAlert(id)); - }, []); + const dismissLegacy = React.useCallback( + (id: string) => { + dispatch(dismissAlert(id)); + }, + [dispatch] + ); return ( <> diff --git a/kafka-ui-react-app/src/components/App.tsx b/kafka-ui-react-app/src/components/App.tsx index 1a74b4e8d5..9be24aa71d 100644 --- a/kafka-ui-react-app/src/components/App.tsx +++ b/kafka-ui-react-app/src/components/App.tsx @@ -36,11 +36,11 @@ const App: React.FC = () => { React.useEffect(() => { closeSidebar(); - }, [location]); + }, [closeSidebar, location]); React.useEffect(() => { dispatch(fetchClusters()); - }, [fetchClusters]); + }, [dispatch]); return ( diff --git a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx index 411f7cf414..3a6466f0b5 100644 --- a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx +++ b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx @@ -35,7 +35,7 @@ const Brokers: React.FC = () => { React.useEffect(() => { dispatch(fetchClusterStats(clusterName)); - }, [fetchClusterStats, clusterName]); + }, [clusterName, dispatch]); useInterval(() => { fetchClusterStats(clusterName); diff --git a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx index 1d603b1a6f..54538de4a7 100644 --- a/kafka-ui-react-app/src/components/Cluster/Cluster.tsx +++ b/kafka-ui-react-app/src/components/Cluster/Cluster.tsx @@ -49,7 +49,12 @@ const Cluster: React.FC = () => { hasSchemaRegistryConfigured, isTopicDeletionAllowed, }), - [features] + [ + hasKafkaConnectConfigured, + hasSchemaRegistryConfigured, + isReadOnly, + isTopicDeletionAllowed, + ] ); return ( diff --git a/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx b/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx index 7f8ce91852..ab19d773ae 100644 --- a/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx +++ b/kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx @@ -70,7 +70,7 @@ const Actions: React.FC = ({ } catch { // do not redirect } - }, [deleteConnector, clusterName, connectName, connectorName]); + }, [deleteConnector, clusterName, connectName, connectorName, history]); const restartConnectorHandler = React.useCallback(() => { restartConnector(clusterName, connectName, connectorName); diff --git a/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx index baf933cfde..ec6dfb21db 100644 --- a/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Connect/Edit/Edit.tsx @@ -100,7 +100,7 @@ const Edit: React.FC = ({ ); } }, - [updateConfig, clusterName, connectName, connectorName] + [updateConfig, clusterName, connectName, connectorName, history] ); if (isConfigFetching) return ; diff --git a/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx b/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx index 231f8ecc76..97eaa1adbb 100644 --- a/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Connect/List/ListItem.tsx @@ -45,7 +45,7 @@ const ListItem: React.FC = ({ dispatch(deleteConnector(clusterName, connect, name)); } setDeleteConnectorConfirmationVisible(false); - }, [clusterName, connect, name]); + }, [clusterName, connect, dispatch, name]); const runningTasks = React.useMemo(() => { if (!tasksCount) return null; diff --git a/kafka-ui-react-app/src/components/Connect/New/New.tsx b/kafka-ui-react-app/src/components/Connect/New/New.tsx index 18b80313fa..a6f5927621 100644 --- a/kafka-ui-react-app/src/components/Connect/New/New.tsx +++ b/kafka-ui-react-app/src/components/Connect/New/New.tsx @@ -101,7 +101,7 @@ const New: React.FC = ({ ); } }, - [createConnector, clusterName] + [createConnector, clusterName, history] ); if (areConnectsFetching) { diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx index d0cd26c7fe..9049a19f7e 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx @@ -18,7 +18,7 @@ const ConsumerGroups: React.FC = () => { const isFetched = useAppSelector(getAreConsumerGroupsFulfilled); React.useEffect(() => { dispatch(fetchConsumerGroups(clusterName)); - }, [fetchConsumerGroups, clusterName]); + }, [clusterName, dispatch]); if (isFetched) { return ( diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx index bd268f208c..ad37373609 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/Details.tsx @@ -47,7 +47,7 @@ const Details: React.FC = () => { React.useEffect(() => { dispatch(fetchConsumerGroupDetails({ clusterName, consumerGroupID })); - }, [fetchConsumerGroupDetails, clusterName, consumerGroupID]); + }, [clusterName, consumerGroupID, dispatch]); const onDelete = () => { setIsConfirmationModalVisible(false); @@ -57,7 +57,7 @@ const Details: React.FC = () => { if (isDeleted) { history.push(clusterConsumerGroupsPath(clusterName)); } - }, [isDeleted]); + }, [clusterName, history, isDeleted]); const onResetOffsets = () => { history.push( diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx index 66377f8bce..253e650940 100644 --- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx +++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx @@ -59,7 +59,7 @@ const ResetOffsets: React.FC = () => { React.useEffect(() => { dispatch(fetchConsumerGroupDetails({ clusterName, consumerGroupID })); - }, [clusterName, consumerGroupID]); + }, [clusterName, consumerGroupID, dispatch]); const [uniqueTopics, setUniqueTopics] = React.useState([]); const [selectedPartitions, setSelectedPartitions] = React.useState( @@ -96,7 +96,7 @@ const ResetOffsets: React.FC = () => { setValue('topic', consumerGroup.partitions[0].topic); setUniqueTopics(Object.keys(groupBy(consumerGroup.partitions, 'topic'))); } - }, [isFetched]); + }, [consumerGroup?.partitions, isFetched, setValue]); const onSelectedPartitionsChange = (value: Option[]) => { clearErrors(); @@ -117,6 +117,7 @@ const ResetOffsets: React.FC = () => { React.useEffect(() => { onSelectedPartitionsChange([]); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [topicValue]); const onSubmit = (data: FormType) => { @@ -169,7 +170,7 @@ const ResetOffsets: React.FC = () => { clusterConsumerGroupDetailsPath(clusterName, consumerGroupID) ); } - }, [isOffsetReseted]); + }, [clusterName, consumerGroupID, dispatch, history, isOffsetReseted]); if (!isFetched || !consumerGroup) { return ; diff --git a/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx b/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx index 0de5323317..388945392f 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/List/List.tsx @@ -32,7 +32,7 @@ const List: FC = () => { useEffect(() => { dispatch(fetchKsqlDbTables(clusterName)); - }, []); + }, [clusterName, dispatch]); return ( <> diff --git a/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx b/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx index b8303eea06..afc8406a21 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/Query/Query.tsx @@ -42,7 +42,7 @@ const Query: FC = () => { useEffect(() => { return reset; - }, []); + }, [reset]); const { handleSubmit, setValue, control } = useForm({ mode: 'onTouched', @@ -53,19 +53,22 @@ const Query: FC = () => { }, }); - const submitHandler = useCallback(async (values: FormValues) => { - dispatch( - executeKsql({ - clusterName, - ksqlCommand: { - ...values, - streamsProperties: values.streamsProperties - ? JSON.parse(values.streamsProperties) - : undefined, - }, - }) - ); - }, []); + const submitHandler = useCallback( + async (values: FormValues) => { + dispatch( + executeKsql({ + clusterName, + ksqlCommand: { + ...values, + streamsProperties: values.streamsProperties + ? JSON.parse(values.streamsProperties) + : undefined, + }, + }) + ); + }, + [clusterName, dispatch] + ); return ( <> diff --git a/kafka-ui-react-app/src/components/KsqlDb/Query/ResultRenderer.tsx b/kafka-ui-react-app/src/components/KsqlDb/Query/ResultRenderer.tsx index d8c8e7cd06..7313a81cb8 100644 --- a/kafka-ui-react-app/src/components/KsqlDb/Query/ResultRenderer.tsx +++ b/kafka-ui-react-app/src/components/KsqlDb/Query/ResultRenderer.tsx @@ -20,6 +20,7 @@ const ResultRenderer: React.FC<{ result: KsqlCommandResponse | null }> = ({ const { headers, rows } = rawTable; + // eslint-disable-next-line react-hooks/rules-of-hooks const transformedRows = React.useMemo( () => rows.map((row) => @@ -31,7 +32,7 @@ const ResultRenderer: React.FC<{ result: KsqlCommandResponse | null }> = ({ {} as Dictionary ) ), - [] + [rawTable.headers, rows] ); return ( diff --git a/kafka-ui-react-app/src/components/Schemas/Details/Details.tsx b/kafka-ui-react-app/src/components/Schemas/Details/Details.tsx index 0ee5916126..2fc85812ef 100644 --- a/kafka-ui-react-app/src/components/Schemas/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Details/Details.tsx @@ -47,14 +47,14 @@ const Details: React.FC = () => { return () => { dispatch(resetLoaderById(SCHEMA_LATEST_FETCH_ACTION)); }; - }, []); + }, [clusterName, dispatch, subject]); React.useEffect(() => { dispatch(fetchSchemaVersions({ clusterName, subject })); return () => { dispatch(resetLoaderById(SCHEMAS_VERSIONS_FETCH_ACTION)); }; - }, [clusterName, subject]); + }, [clusterName, dispatch, subject]); const versions = useAppSelector((state) => selectAllSchemaVersions(state)); const schema = useAppSelector(getSchemaLatest); @@ -72,7 +72,7 @@ const Details: React.FC = () => { const err = await getResponse(e as Response); dispatch(serverErrorAlertAdded(err)); } - }, [clusterName, subject]); + }, [clusterName, dispatch, history, subject]); if (!isFetched || !schema) { return ; diff --git a/kafka-ui-react-app/src/components/Schemas/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Schemas/Edit/Edit.tsx index 11842fc770..eb1991cb49 100644 --- a/kafka-ui-react-app/src/components/Schemas/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Schemas/Edit/Edit.tsx @@ -47,7 +47,7 @@ const Edit: React.FC = () => { return () => { dispatch(resetLoaderById(SCHEMA_LATEST_FETCH_ACTION)); }; - }, [clusterName, subject]); + }, [clusterName, dispatch, subject]); const schema = useAppSelector((state) => getSchemaLatest(state)); const isFetched = useAppSelector(getAreSchemaLatestFulfilled); @@ -58,44 +58,56 @@ const Edit: React.FC = () => { : JSON.stringify(JSON.parse(schema?.schema || '{}'), null, '\t'); }, [schema]); - const onSubmit = React.useCallback(async (props: NewSchemaSubjectRaw) => { - if (!schema) return; + const onSubmit = React.useCallback( + async (props: NewSchemaSubjectRaw) => { + if (!schema) return; - try { - if (dirtyFields.newSchema || dirtyFields.schemaType) { - const resp = await schemasApiClient.createNewSchema({ - clusterName, - newSchemaSubject: { - ...schema, - schema: props.newSchema || schema.schema, - schemaType: props.schemaType || schema.schemaType, - }, - }); - dispatch(schemaAdded(resp)); + try { + if (dirtyFields.newSchema || dirtyFields.schemaType) { + const resp = await schemasApiClient.createNewSchema({ + clusterName, + newSchemaSubject: { + ...schema, + schema: props.newSchema || schema.schema, + schemaType: props.schemaType || schema.schemaType, + }, + }); + dispatch(schemaAdded(resp)); + } + + if (dirtyFields.compatibilityLevel) { + await schemasApiClient.updateSchemaCompatibilityLevel({ + clusterName, + subject, + compatibilityLevel: { + compatibility: props.compatibilityLevel, + }, + }); + dispatch( + schemaUpdated({ + ...schema, + compatibilityLevel: props.compatibilityLevel, + }) + ); + } + + history.push(clusterSchemaPath(clusterName, subject)); + } catch (e) { + const err = await getResponse(e as Response); + dispatch(serverErrorAlertAdded(err)); } - - if (dirtyFields.compatibilityLevel) { - await schemasApiClient.updateSchemaCompatibilityLevel({ - clusterName, - subject, - compatibilityLevel: { - compatibility: props.compatibilityLevel, - }, - }); - dispatch( - schemaUpdated({ - ...schema, - compatibilityLevel: props.compatibilityLevel, - }) - ); - } - - history.push(clusterSchemaPath(clusterName, subject)); - } catch (e) { - const err = await getResponse(e as Response); - dispatch(serverErrorAlertAdded(err)); - } - }, []); + }, + [ + clusterName, + dirtyFields.compatibilityLevel, + dirtyFields.newSchema, + dirtyFields.schemaType, + dispatch, + history, + schema, + subject, + ] + ); if (!isFetched || !schema) { return ; diff --git a/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/GlobalSchemaSelector.tsx b/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/GlobalSchemaSelector.tsx index be7faf3a88..9157d454c6 100644 --- a/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/GlobalSchemaSelector.tsx +++ b/kafka-ui-react-app/src/components/Schemas/List/GlobalSchemaSelector/GlobalSchemaSelector.tsx @@ -48,7 +48,7 @@ const GlobalSchemaSelector: React.FC = () => { }; fetchData(); - }, []); + }, [clusterName]); const handleChangeCompatibilityLevel = (level: string | number) => { setNextCompatibilityLevel(level as CompatibilityLevelCompatibilityEnum); diff --git a/kafka-ui-react-app/src/components/Schemas/List/List.tsx b/kafka-ui-react-app/src/components/Schemas/List/List.tsx index 066d209bc3..5a5de18b14 100644 --- a/kafka-ui-react-app/src/components/Schemas/List/List.tsx +++ b/kafka-ui-react-app/src/components/Schemas/List/List.tsx @@ -41,7 +41,7 @@ const List: React.FC = () => { return () => { dispatch(resetLoaderById(SCHEMAS_FETCH_ACTION)); }; - }, [clusterName, page, perPage, searchText]); + }, [clusterName, dispatch, page, perPage, searchText]); return ( <> diff --git a/kafka-ui-react-app/src/components/Schemas/New/New.tsx b/kafka-ui-react-app/src/components/Schemas/New/New.tsx index 6f753e38b2..d6466f93b1 100644 --- a/kafka-ui-react-app/src/components/Schemas/New/New.tsx +++ b/kafka-ui-react-app/src/components/Schemas/New/New.tsx @@ -55,7 +55,7 @@ const New: React.FC = () => { dispatch(serverErrorAlertAdded(err)); } }, - [clusterName] + [clusterName, dispatch, history] ); return ( diff --git a/kafka-ui-react-app/src/components/Topics/List/List.tsx b/kafka-ui-react-app/src/components/Topics/List/List.tsx index fc54ae61ba..fd75c87a91 100644 --- a/kafka-ui-react-app/src/components/Topics/List/List.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/List.tsx @@ -93,7 +93,7 @@ const List: React.FC = ({ const handleSwitch = React.useCallback(() => { setShowInternal(!showInternal); history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`); - }, [showInternal]); + }, [history, pathname, perPage, showInternal]); const [confirmationModal, setConfirmationModal] = React.useState< '' | 'deleteTopics' | 'purgeMessages' @@ -127,18 +127,18 @@ const List: React.FC = ({ deleteTopics(clusterName, Array.from(selectedTopics)); closeConfirmationModal(); clearSelectedTopics(); - }, [clusterName, selectedTopics]); + }, [clusterName, deleteTopics, selectedTopics]); const purgeMessagesHandler = React.useCallback(() => { clearTopicsMessages(clusterName, Array.from(selectedTopics)); closeConfirmationModal(); clearSelectedTopics(); - }, [clusterName, selectedTopics]); + }, [clearTopicsMessages, clusterName, selectedTopics]); const searchHandler = React.useCallback( (searchString: string) => { setTopicsSearch(searchString); history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`); }, - [search, pathname, perPage] + [setTopicsSearch, history, pathname, perPage] ); return ( diff --git a/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx b/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx index 7b065401a0..1374aa16a6 100644 --- a/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx @@ -70,11 +70,11 @@ const ListItem: React.FC = ({ const deleteTopicHandler = React.useCallback(() => { deleteTopic(clusterName, name); - }, [clusterName, name]); + }, [clusterName, deleteTopic, name]); const clearTopicMessagesHandler = React.useCallback(() => { clearTopicMessages(clusterName, name); - }, [clusterName, name]); + }, [clearTopicMessages, clusterName, name]); const [vElipsisVisble, setVElipsisVisble] = React.useState(false); return ( diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx index d35fd934ac..5c67e23007 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/ConsumerGroups/TopicConsumerGroups.tsx @@ -27,7 +27,7 @@ const TopicConsumerGroups: React.FC = ({ }) => { React.useEffect(() => { fetchTopicConsumerGroups(clusterName, topicName); - }, []); + }, [clusterName, fetchTopicConsumerGroups, topicName]); return (
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx index f83c662762..c6e8f9c0e0 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx @@ -64,19 +64,19 @@ const Details: React.FC = ({ React.useState(false); const deleteTopicHandler = React.useCallback(() => { deleteTopic(clusterName, topicName); - }, [clusterName, topicName]); + }, [clusterName, deleteTopic, topicName]); React.useEffect(() => { if (isDeleted) { dispatch(deleteTopicAction.cancel()); history.push(clusterTopicsPath(clusterName)); } - }, [isDeleted]); + }, [clusterName, dispatch, history, isDeleted]); const clearTopicMessagesHandler = React.useCallback(() => { clearTopicMessages(clusterName, topicName); setClearTopicConfirmationVisible(false); - }, [clusterName, topicName]); + }, [clearTopicMessages, clusterName, topicName]); return (
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx index 7adb3e71e6..2dba1028f6 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx @@ -126,7 +126,7 @@ const Filters: React.FC = ({ [partitions] ); - const handleFiltersSubmit = () => { + const handleFiltersSubmit = React.useCallback(() => { setAttempt(attempt + 1); const props: Query = { @@ -166,7 +166,8 @@ const Filters: React.FC = ({ history.push({ search: `?${qs}`, }); - }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const toggleSeekDirection = (val: string) => { const nextSeekDirectionValue = @@ -224,17 +225,26 @@ const Filters: React.FC = ({ sse.close(); }; } - }, [clusterName, topicName, location]); + }, [ + clusterName, + topicName, + location, + setIsFetching, + resetMessages, + addMessage, + updatePhase, + updateMeta, + ]); React.useEffect(() => { if (location.search.length === 0) { handleFiltersSubmit(); } - }, [location]); + }, [handleFiltersSubmit, location]); React.useEffect(() => { handleFiltersSubmit(); - }, [seekDirection]); + }, [handleFiltersSubmit, seekDirection]); return ( diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessagesTable.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessagesTable.tsx index 28256caf11..a5e0962210 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessagesTable.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessagesTable.tsx @@ -27,7 +27,7 @@ const MessagesTable: React.FC = () => { const searchParams = React.useMemo( () => new URLSearchParams(location.search), - [location, history] + [location] ); const messages = useSelector(getTopicMessges); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx index 17f49f5488..33f597e0c9 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/Edit.tsx @@ -88,10 +88,7 @@ const Edit: React.FC = ({ fetchTopicConfig, updateTopic, }) => { - const defaultValues = React.useMemo( - () => topicParams(topic), - [topicParams, topic] - ); + const defaultValues = React.useMemo(() => topicParams(topic), [topic]); const methods = useForm({ defaultValues, resolver: yupResolver(topicFormValidationSchema), @@ -109,7 +106,7 @@ const Edit: React.FC = ({ const { name } = methods.getValues(); history.push(clusterTopicPath(clusterName, name)); } - }, [isSubmitting, isTopicUpdated, clusterTopicPath, clusterName, methods]); + }, [isSubmitting, isTopicUpdated, clusterName, methods, history]); if (!isFetched || !topic || !topic.config) { return null; diff --git a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx index 06de822caa..ee1ba03de4 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx @@ -41,7 +41,7 @@ const SendMessage: React.FC = () => { React.useEffect(() => { dispatch(fetchTopicMessageSchema(clusterName, topicName)); - }, []); + }, [clusterName, dispatch, topicName]); const messageSchema = useAppSelector((state) => getMessageSchemaByTopicName(state, topicName) diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamField.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamField.tsx index c076f76503..5984247a75 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamField.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamField.tsx @@ -54,7 +54,7 @@ const CustomParamField: React.FC = ({ shouldValidate: true, }); } - }, [nameValue]); + }, [existingFields, index, nameValue, setExistingFields, setValue]); return ( diff --git a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx index a34e0b0cfa..bbbac922a6 100644 --- a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx +++ b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.route.tsx @@ -15,6 +15,7 @@ const BreadcrumbRouteInternal: React.FC = () => { useEffect(() => { context.handleRouteChange({ ...match, url: location.pathname }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [location.pathname]); return null; diff --git a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx index 7cfca3a83c..5196d77600 100644 --- a/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx +++ b/kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx @@ -13,7 +13,7 @@ const Breadcrumb: React.FC = () => { const links = React.useMemo( () => breadcrumbContext.path.slice(basePathEntriesLength), - [breadcrumbContext.link] + [breadcrumbContext.path] ); const getPathPredicate = React.useCallback( diff --git a/kafka-ui-react-app/src/components/common/BytesFormatted/BytesFormatted.tsx b/kafka-ui-react-app/src/components/common/BytesFormatted/BytesFormatted.tsx index ad45e454db..7cfb35cfd2 100644 --- a/kafka-ui-react-app/src/components/common/BytesFormatted/BytesFormatted.tsx +++ b/kafka-ui-react-app/src/components/common/BytesFormatted/BytesFormatted.tsx @@ -21,7 +21,7 @@ const BytesFormatted: React.FC = ({ value, precision = 0 }) => { } catch (e) { return `-Bytes`; } - }, [value]); + }, [precision, value]); return {formatedValue}; }; diff --git a/kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx b/kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx index 1af2bf42cd..763ce3b8a4 100644 --- a/kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx +++ b/kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx @@ -19,14 +19,14 @@ const ConfirmationModal: React.FC = ({ onConfirm, isConfirming = false, }) => { - if (!isOpen) return null; - const cancelHandler = React.useCallback(() => { if (!isConfirming) { onCancel(); } }, [isConfirming, onCancel]); + if (!isOpen) return null; + return (