lint: fix sonarjs/no-dead-store issues (#23653)

This commit is contained in:
Matri Qi
2025-08-10 11:16:43 +08:00
committed by GitHub
parent 79a3c1618f
commit ea502d36a9
19 changed files with 17 additions and 76 deletions

View File

@@ -4,7 +4,6 @@ import React, { useEffect, useMemo } from 'react'
import { usePathname } from 'next/navigation'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import {
RiEqualizer2Fill,
RiEqualizer2Line,
@@ -44,17 +43,12 @@ type IExtraInfoProps = {
}
const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
const { t } = useTranslation()
const docLink = useDocLink()
const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
const relatedAppsTotal = relatedApps?.data?.length || 0
useEffect(() => {
setShowTips(!isMobile)
}, [isMobile, setShowTips])
return <div>
{/* Related apps for desktop */}
<div className={classNames(

View File

@@ -55,8 +55,6 @@ const SettingsModal: FC<SettingsModalProps> = ({
const { data: embeddingsModelList } = useModelList(ModelTypeEnum.textEmbedding)
const {
modelList: rerankModelList,
defaultModel: rerankDefaultModel,
currentModel: isRerankDefaultModelValid,
} = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank)
const { t } = useTranslation()
const docLink = useDocLink()

View File

@@ -81,7 +81,6 @@ const CodeBlock: any = memo(({ inline, className, children = '', ...props }: any
const echartsRef = useRef<any>(null)
const contentRef = useRef<string>('')
const processedRef = useRef<boolean>(false) // Track if content was successfully processed
const instanceIdRef = useRef<string>(`chart-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`) // Unique ID for logging
const isInitialRenderRef = useRef<boolean>(true) // Track if this is initial render
const chartInstanceRef = useRef<any>(null) // Direct reference to ECharts instance
const resizeTimerRef = useRef<NodeJS.Timeout | null>(null) // For debounce handling

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import mermaid, { type MermaidConfig } from 'mermaid'
import { useTranslation } from 'react-i18next'
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'
@@ -122,14 +122,6 @@ const Flowchart = React.forwardRef((props: {
const renderTimeoutRef = useRef<NodeJS.Timeout>()
const [errMsg, setErrMsg] = useState('')
const [imagePreviewUrl, setImagePreviewUrl] = useState('')
const [isCodeComplete, setIsCodeComplete] = useState(false)
const codeCompletionCheckRef = useRef<NodeJS.Timeout>()
const prevCodeRef = useRef<string>()
// Create cache key from code, style and theme
const cacheKey = useMemo(() => {
return `${props.PrimitiveCode}-${look}-${currentTheme}`
}, [props.PrimitiveCode, look, currentTheme])
/**
* Renders Mermaid chart
@@ -537,11 +529,9 @@ const Flowchart = React.forwardRef((props: {
{isLoading && !svgString && (
<div className='px-[26px] py-4'>
<LoadingAnim type='text'/>
{!isCodeComplete && (
<div className="mt-2 text-sm text-gray-500">
{t('common.wait_for_completion', 'Waiting for diagram code to complete...')}
</div>
)}
</div>
)}

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React from 'react'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { RiBookOpenLine } from '@remixicon/react'
@@ -28,10 +28,8 @@ const Form: FC<FormProps> = React.memo(({
}) => {
const { t, i18n } = useTranslation()
const docLink = useDocLink()
const [changeKey, setChangeKey] = useState('')
const handleFormChange = (key: string, val: string) => {
setChangeKey(key)
if (key === 'name') {
onChange({ ...value, [key]: val })
}

View File

@@ -28,8 +28,8 @@ const RenameDatasetModal = ({ show, dataset, onSuccess, onClose }: RenameDataset
const [loading, setLoading] = useState(false)
const [name, setName] = useState<string>(dataset.name)
const [description, setDescription] = useState<string>(dataset.description)
const [externalKnowledgeId, setExternalKnowledgeId] = useState<string>(dataset.external_knowledge_info.external_knowledge_id)
const [externalKnowledgeApiId, setExternalKnowledgeApiId] = useState<string>(dataset.external_knowledge_info.external_knowledge_api_id)
const externalKnowledgeId = dataset.external_knowledge_info.external_knowledge_id
const externalKnowledgeApiId = dataset.external_knowledge_info.external_knowledge_api_id
const onConfirm: MouseEventHandler = async () => {
if (!name.trim()) {

View File

@@ -51,7 +51,6 @@ const Apps = ({
handleSearch()
}
const [currentType, setCurrentType] = useState<string>('')
const [currCategory, setCurrCategory] = useTabSearchParams({
defaultTab: allCategoriesEn,
disableSearchParams: false,
@@ -74,28 +73,7 @@ const Apps = ({
},
)
const filteredList = useMemo(() => {
if (currCategory === allCategoriesEn) {
if (!currentType)
return allList
else if (currentType === 'chatbot')
return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat'))
else if (currentType === 'agent')
return allList.filter(item => (item.app.mode === 'agent-chat'))
else
return allList.filter(item => (item.app.mode === 'workflow'))
}
else {
if (!currentType)
return allList.filter(item => item.category === currCategory)
else if (currentType === 'chatbot')
return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat') && item.category === currCategory)
else if (currentType === 'agent')
return allList.filter(item => (item.app.mode === 'agent-chat') && item.category === currCategory)
else
return allList.filter(item => (item.app.mode === 'workflow') && item.category === currCategory)
}
}, [currentType, currCategory, allCategoriesEn, allList])
const filteredList = allList.filter(item => currCategory === allCategoriesEn || item.category === currCategory)
const searchFilteredList = useMemo(() => {
if (!searchKeywords || !filteredList || filteredList.length === 0)

View File

@@ -49,7 +49,6 @@ const SideBar: FC<IExploreSideBarProps> = ({
const segments = useSelectedLayoutSegments()
const lastSegment = segments.slice(-1)[0]
const isDiscoverySelected = lastSegment === 'apps'
const isChatSelected = lastSegment === 'chat'
const { installedApps, setInstalledApps, setIsFetchingInstalledApps } = useContext(ExploreContext)
const { isFetching: isFetchingInstalledApps, data: ret, refetch: fetchInstalledAppList } = useGetInstalledApps()
const { mutateAsync: uninstallApp } = useUninstallApp()

View File

@@ -1,11 +1,10 @@
'use client'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { t } from 'i18next'
import copy from 'copy-to-clipboard'
import s from './index.module.css'
import type { SuccessInvitationResult } from '.'
import Tooltip from '@/app/components/base/tooltip'
import { randomString } from '@/utils'
type IInvitationLinkProps = {
value: SuccessInvitationResult
@@ -15,7 +14,6 @@ const InvitationLink = ({
value,
}: IInvitationLinkProps) => {
const [isCopied, setIsCopied] = useState(false)
const selector = useRef(`invite-link-${randomString(4)}`)
const copyHandle = useCallback(() => {
// No prefix is needed here because the backend has already processed it

View File

@@ -1,7 +1,6 @@
import type { FC } from 'react'
import { useEffect, useRef, useState } from 'react'
import type { ModelParameterRule } from '../declarations'
import { useLanguage } from '../hooks'
import { isNullOrUndefined } from '../utils'
import cn from '@/utils/classnames'
import Switch from '@/app/components/base/switch'
@@ -10,7 +9,6 @@ import Slider from '@/app/components/base/slider'
import Radio from '@/app/components/base/radio'
import { SimpleSelect } from '@/app/components/base/select'
import TagInput from '@/app/components/base/tag-input'
import { useTranslation } from 'react-i18next'
export type ParameterValue = number | string | string[] | boolean | undefined
@@ -28,8 +26,6 @@ const ParameterItem: FC<ParameterItemProps> = ({
onSwitch,
isInWorkflow,
}) => {
const { t } = useTranslation()
const language = useLanguage()
const [localValue, setLocalValue] = useState(value)
const numberInputRef = useRef<HTMLInputElement>(null)

View File

@@ -30,7 +30,7 @@ const TagsFilter = ({
const { t } = useMixedTranslation(locale)
const [open, setOpen] = useState(false)
const [searchText, setSearchText] = useState('')
const { tags: options, tagsMap } = useTags(t)
const { tags: options } = useTags(t)
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchText.toLowerCase()))
const handleCheck = (id: string) => {
if (tags.includes(id))
@@ -38,7 +38,6 @@ const TagsFilter = ({
else
onTagsChange([...tags, id])
}
const selectedTagsLength = tags.length
return (
<PortalToFollowElem

View File

@@ -45,7 +45,7 @@ export const getPluginDetailLinkInMarketplace = (plugin: Plugin) => {
}
export const getMarketplacePluginsByCollectionId = async (collectionId: string, query?: CollectionsAndPluginsSearchParams) => {
let plugins = [] as Plugin[]
let plugins: Plugin[]
try {
const url = `${MARKETPLACE_API_PREFIX}/collections/${collectionId}/plugins`

View File

@@ -151,10 +151,9 @@ const TextGeneration: FC<IMainProps> = ({
const pendingTaskList = allTaskList.filter(task => task.status === TaskStatus.pending)
const noPendingTask = pendingTaskList.length === 0
const showTaskList = allTaskList.filter(task => task.status !== TaskStatus.pending)
const [currGroupNum, doSetCurrGroupNum] = useState(0)
const currGroupNumRef = useRef(0)
const setCurrGroupNum = (num: number) => {
doSetCurrGroupNum(num)
currGroupNumRef.current = num
}
const getCurrGroupNum = () => {
@@ -164,10 +163,8 @@ const TextGeneration: FC<IMainProps> = ({
const allFailedTaskList = allTaskList.filter(task => task.status === TaskStatus.failed)
const allTasksFinished = allTaskList.every(task => task.status === TaskStatus.completed)
const allTasksRun = allTaskList.every(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status))
const [batchCompletionRes, doSetBatchCompletionRes] = useState<Record<string, string>>({})
const batchCompletionResRef = useRef<Record<string, string>>({})
const setBatchCompletionRes = (res: Record<string, string>) => {
doSetBatchCompletionRes(res)
batchCompletionResRef.current = res
}
const getBatchCompletionRes = () => batchCompletionResRef.current

View File

@@ -23,7 +23,7 @@ const useStickyScroll = ({
return
const { height: wrapHeight, top: wrapTop } = wrapDom.getBoundingClientRect()
const { top: nextToStickyTop } = stickyDOM.getBoundingClientRect()
let scrollPositionNew = ScrollPosition.belowTheWrap
let scrollPositionNew: ScrollPosition
if (nextToStickyTop - wrapTop >= wrapHeight)
scrollPositionNew = ScrollPosition.belowTheWrap

View File

@@ -444,7 +444,7 @@ export const useFetchToolsData = () => {
workflowTools: workflowTools || [],
})
}
if(type === 'mcp') {
if (type === 'mcp') {
const mcpTools = await fetchAllMCPTools()
workflowStore.setState({
@@ -500,18 +500,17 @@ export const useToolIcon = (data: Node['data']) => {
const mcpTools = useStore(s => s.mcpTools)
const toolIcon = useMemo(() => {
if(!data)
if (!data)
return ''
if (data.type === BlockEnum.Tool) {
let targetTools = buildInTools
let targetTools = workflowTools
if (data.provider_type === CollectionType.builtIn)
targetTools = buildInTools
else if (data.provider_type === CollectionType.custom)
targetTools = customTools
else if (data.provider_type === CollectionType.mcp)
targetTools = mcpTools
else
targetTools = workflowTools
return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon
}
}, [data, buildInTools, customTools, mcpTools, workflowTools])

View File

@@ -11,7 +11,6 @@ import {
import {
useNodeDataUpdate,
useNodesInteractions,
useNodesSyncDraft,
} from '../../../hooks'
import { type Node, NodeRunningStatus } from '../../../types'
import { canRunBySingle } from '../../../utils'
@@ -30,7 +29,6 @@ const NodeControl: FC<NodeControlProps> = ({
const [open, setOpen] = useState(false)
const { handleNodeDataUpdate } = useNodeDataUpdate()
const { handleNodeSelect } = useNodesInteractions()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const isSingleRunning = data._singleRunningStatus === NodeRunningStatus.Running
const handleOpenChange = useCallback((newOpen: boolean) => {
setOpen(newOpen)

View File

@@ -198,7 +198,6 @@ const BasePanel: FC<BasePanelProps> = ({
isShowSingleRun,
hideSingleRun,
runningStatus,
handleStop,
runInputData,
runInputDataRef,
runResult,

View File

@@ -36,6 +36,7 @@ const useConfig = (id: string, payload: ListFilterNodeType) => {
const { inputs, setInputs } = useNodeCrud<ListFilterNodeType>(id, payload)
const { getCurrentVariableType } = useWorkflowVariables()
const getType = useCallback((variable?: ValueSelector) => {
const varType = getCurrentVariableType({
parentNode: isInIteration ? iterationNode : loopNode,
@@ -44,7 +45,7 @@ const useConfig = (id: string, payload: ListFilterNodeType) => {
isChatMode,
isConstant: false,
})
let itemVarType = VarType.string
let itemVarType = varType
switch (varType) {
case VarType.arrayNumber:
itemVarType = VarType.number
@@ -58,8 +59,6 @@ const useConfig = (id: string, payload: ListFilterNodeType) => {
case VarType.arrayObject:
itemVarType = VarType.object
break
default:
itemVarType = varType
}
return { varType, itemVarType }
}, [availableNodes, getCurrentVariableType, inputs.variable, isChatMode, isInIteration, iterationNode, loopNode])

View File

@@ -163,7 +163,7 @@ export default combine(
'sonarjs/single-char-in-character-classes': 'off',
'sonarjs/anchor-precedence': 'warn',
'sonarjs/updated-loop-counter': 'off',
'sonarjs/no-dead-store': 'warn',
'sonarjs/no-dead-store': 'error',
'sonarjs/no-duplicated-branches': 'warn',
'sonarjs/max-lines': 'warn', // max 1000 lines
'sonarjs/no-variable-usage-before-declaration': 'error',