Skip to content

React useCallback hook Dependencies useExhaustiveDependencies - getting incorrect linting #5914

@shmdhussain

Description

@shmdhussain

Environment information

CLI:
  Version:                      1.9.4
  Color support:                true

Platform:
  CPU Architecture:             aarch64
  OS:                           macos

Environment:
  BIOME_LOG_PATH:               unset
  BIOME_LOG_PREFIX_NAME:        unset
  BIOME_CONFIG_PATH:            unset
  NO_COLOR:                     unset
  TERM:                         "xterm-256color"
  JS_RUNTIME_VERSION:           "v20.12.0"
  JS_RUNTIME_NAME:              "node"
  NODE_PACKAGE_MANAGER:         unset

Biome Configuration:
  Status:                       Loaded successfully
  Formatter disabled:           false
  Linter disabled:              false
  Organize imports disabled:    false
  VCS disabled:                 true

Linter:
  JavaScript enabled:           true
  JSON enabled:                 true
  CSS enabled:                  true
  GraphQL enabled:              false
  Recommended:                  true
  All:                          false
  Enabled rules:
  performance/noDelete
  suspicious/noCatchAssign
  suspicious/noUnsafeNegation
  complexity/useLiteralKeys
  suspicious/noClassAssign
  style/useImportType
  complexity/noMultipleSpacesInRegularExpressionLiterals
  a11y/useValidLang
  complexity/noUselessEmptyExport
  suspicious/useNamespaceKeyword
  suspicious/useValidTypeof
  a11y/useValidAriaRole
  correctness/noConstantCondition
  a11y/useAriaActivedescendantWithTabindex
  suspicious/noAssignInExpressions
  style/useDefaultParameterLast
  complexity/noEmptyTypeParameters
  correctness/noConstructorReturn
  style/useSelfClosingElements
  suspicious/noDuplicateParameters
  suspicious/noDuplicateSelectorsKeyframeBlock
  correctness/noUnknownProperty
  style/useTemplate
  correctness/noUnusedLabels
  complexity/noUselessTernary
  correctness/noUnreachableSuper
  suspicious/noCompareNegZero
  suspicious/noExplicitAny
  correctness/noSwitchDeclarations
  a11y/noAutofocus
  correctness/noUnsafeOptionalChaining
  correctness/noConstAssign
  suspicious/noControlCharactersInRegex
  complexity/noUselessTypeConstraint
  style/noVar
  suspicious/noDoubleEquals
  suspicious/noRedundantUseStrict
  style/useLiteralEnumMembers
  suspicious/noGlobalIsNan
  suspicious/noEmptyInterface
  suspicious/noConstEnum
  suspicious/noMisleadingCharacterClass
  correctness/noPrecisionLoss
  a11y/noLabelWithoutControl
  suspicious/noRedeclare
  correctness/noStringCaseMismatch
  correctness/noSetterReturn
  correctness/noInvalidConstructorSuper
  suspicious/noImplicitAnyLet
  suspicious/noFallthroughSwitchClause
  suspicious/noUnsafeDeclarationMerging
  complexity/noUselessThisAlias
  correctness/noUnreachable
  a11y/useKeyWithClickEvents
  suspicious/noDuplicateObjectKeys
  complexity/noThisInStatic
  complexity/useOptionalChain
  correctness/noInnerDeclarations
  style/noParameterAssign
  suspicious/noDuplicateCase
  a11y/useValidAnchor
  complexity/useRegexLiterals
  correctness/noSelfAssign
  correctness/noInvalidBuiltinInstantiation
  style/noUselessElse
  style/useShorthandFunctionType
  suspicious/noShadowRestrictedNames
  correctness/noInvalidDirectionInLinearGradient
  suspicious/noImportantInKeyframe
  a11y/useMediaCaption
  complexity/noUselessLabel
  complexity/noUselessCatch
  correctness/noUnsafeFinally
  a11y/useAriaPropsForRole
  correctness/noNonoctalDecimalEscape
  style/useEnumInitializers
  a11y/useHtmlLang
  suspicious/noDuplicateTestHooks
  complexity/noStaticOnlyClass
  style/useWhile
  complexity/useArrowFunction
  style/noInferrableTypes
  a11y/noNoninteractiveTabindex
  complexity/useSimpleNumberKeys
  correctness/useYield
  a11y/noInteractiveElementToNoninteractiveRole
  style/useNumericLiterals
  correctness/noUnnecessaryContinue
  suspicious/noApproximativeNumericConstant
  suspicious/noImportAssign
  suspicious/noLabelVar
  correctness/noGlobalObjectCalls
  suspicious/useDefaultSwitchClauseLast
  correctness/noUnknownUnit
  a11y/useAltText
  correctness/noEmptyCharacterClassInRegex
  suspicious/noSparseArray
  a11y/useIframeTitle
  complexity/noBannedTypes
  a11y/noSvgWithoutTitle
  correctness/noVoidElementsWithChildren
  style/useAsConstAssertion
  correctness/useJsxKeyInIterable
  style/useExportType
  complexity/noUselessLoneBlockStatements
  suspicious/noDebugger
  style/noArguments
  a11y/useValidAriaValues
  suspicious/noCommentText
  a11y/useFocusableInteractive
  correctness/noUnmatchableAnbSelector
  suspicious/noGlobalAssign
  suspicious/noDuplicateJsxProps
  suspicious/noMisleadingInstantiator
  a11y/noPositiveTabindex
  correctness/noEmptyPattern
  complexity/noExcessiveNestedTestSuites
  security/noDangerouslySetInnerHtmlWithChildren
  a11y/useKeyWithMouseEvents
  suspicious/noExtraNonNullAssertion
  suspicious/noShorthandPropertyOverrides
  correctness/noRenderReturnValue
  correctness/useExhaustiveDependencies
  security/noGlobalEval
  style/noNonNullAssertion
  a11y/noRedundantRoles
  complexity/useFlatMap
  correctness/useIsNan
  style/useConst
  suspicious/noGlobalIsFinite
  suspicious/noSelfCompare
  suspicious/noThenProperty
  suspicious/noAsyncPromiseExecutor
  suspicious/noDuplicateFontNames
  suspicious/useGetterReturn
  security/noDangerouslySetInnerHtml
  style/useNodejsImportProtocol
  a11y/noDistractingElements
  suspicious/noArrayIndexKey
  complexity/noWith
  suspicious/noDuplicateClassMembers
  complexity/noExtraBooleanCast
  performance/noAccumulatingSpread
  a11y/useValidAriaProps
  a11y/noRedundantAlt
  correctness/noChildrenProp
  correctness/noUnknownFunction
  correctness/noInvalidPositionAtImportRule
  suspicious/noConfusingLabels
  suspicious/noPrototypeBuiltins
  suspicious/noConfusingVoidType
  suspicious/noFocusedTests
  a11y/useButtonType
  a11y/useSemanticElements
  a11y/noAriaUnsupportedElements
  correctness/noInvalidGridAreas
  correctness/noFlatMapIdentity
  suspicious/noSuspiciousSemicolonInJsx
  a11y/noBlankTarget
  a11y/useHeadingContent
  correctness/useValidForDirection
  correctness/noVoidTypeReturn
  correctness/noInvalidUseBeforeDeclaration
  a11y/noAriaHiddenOnFocusable
  a11y/useGenericFontNames
  correctness/noUnknownMediaFeatureName
  a11y/useAnchorContent
  complexity/noUselessRename
  style/useNumberNamespace
  complexity/noUselessConstructor
  a11y/noAccessKey
  style/useExponentiationOperator
  style/noUnusedTemplateLiteral
  complexity/noUselessSwitchCase
  style/useSingleVarDeclarator
  suspicious/noExportsInTest
  a11y/noNoninteractiveElementToInteractiveRole
  style/noCommaOperator
  suspicious/noDuplicateAtImportRules
  suspicious/useIsArray
  a11y/noHeaderScope
  complexity/noUselessFragments
  suspicious/noMisrefactoredShorthandAssign
  suspicious/noEmptyBlock
  complexity/noForEach
  correctness/noUnusedImports
  suspicious/noFunctionAssign

Workspace:
  Open Documents:               0

Rule name

lint/correctness/useExhaustiveDependencies

Playground link

https://biomejs.dev/playground/?lintRules=all&files.main.jsx=aQBtAHAAbwByAHQAIAB7ACAAdQBzAGUAUwB0AGEAdABlACwAIAB1AHMAZQBDAGEAbABsAGIAYQBjAGsALAAgAHUAcwBlAEMAbwBuAHQAZQB4AHQALAAgAGMAcgBlAGEAdABlAEMAbwBuAHQAZQB4AHQAIAB9ACAAZgByAG8AbQAgACIAcgBlAGEAYwB0ACIAOwAKAGkAbQBwAG8AcgB0ACAAewAgAGQAZQBiAG8AdQBuAGMAZQAgAH0AIABmAHIAbwBtACAAIgBsAG8AZABhAHMAaAAiADsACgBjAG8AbgBzAHQAIABUAGUAcwB0AEMAbwBuAHQAZQB4AHQAIAA9ACAAUgBlAGEAYwB0AC4AYwByAGUAYQB0AGUAQwBvAG4AdABlAHgAdAAoACkAOwAKAGUAeABwAG8AcgB0ACAAZgB1AG4AYwB0AGkAbwBuACAAVABlAHMAdAAoACkAIAB7AAoACQBjAG8AbgBzAHQAIABbAHEALAAgAHMAZQB0AFEAXQAgAD0AIAB1AHMAZQBTAHQAYQB0AGUAKAAiACIAKQA7AAoACQBjAG8AbgBzAHQAIABvAG4AUwBlAGEAcgBjAGgAIAA9ACAAKAApACAAPQA%2BACAAewAKAAoACQAJAGMAbwBuAHMAbwBsAGUALgBsAG8AZwAoACIAcwBlAGEAcgBjAGgAZQBkACAAdABlAHgAdAAgAGkAcwAiACwAIABxACkAOwAKAAkAfQA7AAoACQByAGUAdAB1AHIAbgAgACgACgAJAAkAPABUAGUAcwB0AEMAbwBuAHQAZQB4AHQALgBwAHIAbwB2AGkAZABlAHIAIAB2AGEAbAB1AGUAPQB7AG8AbgBTAGUAYQByAGMAaAB9AD4ACgAJAAkACQA8AGkAbgBwAHUAdAAKAAkACQAJAAkAdgBhAGwAdQBlAD0AewBxAH0ACgAJAAkACQAJAG8AbgBDAGgAYQBuAGcAZQA9AHsAKABlACkAIAA9AD4AIAB7AAoACQAJAAkACQAJAHMAZQB0AFEAKABlAC4AdABhAHIAZwBlAHQALgB2AGEAbAB1AGUAKQA7AAoACQAJAAkACQB9AH0ACgAJAAkACQAvAD4ACgAJAAkACQA8AE0AeQBTAGUAYQByAGMAaABCAHQAbgAgAC8APgAKAAkACQA8AC8AVABlAHMAdABDAG8AbgB0AGUAeAB0AC4AcAByAG8AdgBpAGQAZQByAD4ACgAJACkAOwAKAH0ACgAKAGUAeABwAG8AcgB0ACAAZgB1AG4AYwB0AGkAbwBuACAATQB5AFMAZQBhAHIAYwBoAEIAdABuACgAKQAgAHsACgAJAGMAbwBuAHMAdAAgAHMAZQBhAHIAYwBoAEMAbwBuAHQAZQB4AHQAIAA9ACAAdQBzAGUAQwBvAG4AdABlAHgAdAAoAFQAZQBzAHQAQwBvAG4AdABlAHgAdAApADsACgAJAGMAbwBuAHMAdAAgAHsAIABvAG4AUwBlAGEAcgBjAGgAIAB9ACAAPQAgAHMAZQBhAHIAYwBoAEMAbwBuAHQAZQB4AHQAOwAKAAoACQAvAC8AYQBjAHQAdQBhAGwAOgAgAGUAcgByAG8AcgAsACAAZQB4AHAAZQBjAHQAZQBkADoAIABlAHIAcgBvAHIAIAAtAC0AIABTAGMAZQBuAGEAcgBpAG8AIABBAAoACQBjAG8AbgBzAHQAIABvAG4AUwBlAGEAcgBjAGgATABvAGMAYQBsADEAIAA9ACAAdQBzAGUAQwBhAGwAbABiAGEAYwBrACgAKAApACAAPQA%2BACAAewAKAAkACQBvAG4AUwBlAGEAcgBjAGgAKAApADsACgAJAH0ALAAgAFsAXQApADsACgAKAAkALwAvAGEAYwB0AHUAYQBsADoAIABuAG8AIABlAHIAcgBvAHIALAAgAGUAeABwAGUAYwB0AGUAZAA6ACAAZQByAHIAbwByACAALQAtACAAUwBjAGUAbgBhAHIAaQBvACAAQgAKAAkAYwBvAG4AcwB0ACAAbwBuAFMAZQBhAHIAYwBoAEwAbwBjAGEAbAAyACAAPQAgAHUAcwBlAEMAYQBsAGwAYgBhAGMAawAoACgAKQA9AD4AZABlAGIAbwB1AG4AYwBlACgAbwBuAFMAZQBhAHIAYwBoACwAIAAxADUAMAApACwAIABbAF0AKQA7AAoACgAJAC8ALwBhAGMAdAB1AGEAbAA6ACAAbgBvACAAZQByAHIAbwByACwAIABlAHgAcABlAGMAdABlAGQAOgAgAGUAcgByAG8AcgAgAC0ALQAgAFMAYwBlAG4AYQByAGkAbwAgAEMACgAJAGMAbwBuAHMAdAAgAG8AbgBTAGUAYQByAGMAaABMAG8AYwBhAGwAMwAgAD0AIAB1AHMAZQBDAGEAbABsAGIAYQBjAGsAKABvAG4AUwBlAGEAcgBjAGgALAAgAFsAXQApADsACgAKACAAIAAgACAALwAvAGEAYwB0AHUAYQBsADoAIABuAG8AIABlAHIAcgBvAHIALAAgAGUAeABwAGUAYwB0AGUAZAA6ACAAZQByAHIAbwByACAALQAtACAAUwBjAGUAbgBhAHIAaQBvACAARAAKAAkAYwBvAG4AcwB0ACAAbwBuAFMAZQBhAHIAYwBoAEwAbwBjAGEAbAA0ACAAPQAgAHUAcwBlAEMAYQBsAGwAYgBhAGMAawAoAG8AbgBTAGUAYQByAGMAaAAsACAAWwBvAG4AUwBlAGEAcgBjAGgAXQApADsACgAKAAoAIAAgAAoACQByAGUAdAB1AHIAbgAgACgACgAJAAkAPAA%2BAAoACQAJAAkAPABiAHUAdAB0AG8AbgAgAG8AbgBDAGwAaQBjAGsAPQB7AG8AbgBTAGUAYQByAGMAaABMAG8AYwBhAGwAMQB9ACAAdAB5AHAAZQA9ACIAYgB1AHQAdABvAG4AIgA%2BAAoACQAJAAkACQBDAGwAaQBjAGsAIABmAG8AcgAgAHMAZQBhAHIAYwBoACAAMQAKAAkACQAJADwALwBiAHUAdAB0AG8AbgA%2BAAoACQAJAAkAPABiAHUAdAB0AG8AbgAgAG8AbgBDAGwAaQBjAGsAPQB7AG8AbgBTAGUAYQByAGMAaABMAG8AYwBhAGwAMgB9ACAAdAB5AHAAZQA9ACIAYgB1AHQAdABvAG4AIgA%2BAAoACQAJAAkACQBDAGwAaQBjAGsAIABmAG8AcgAgAHMAZQBhAHIAYwBoACAAMgAKAAkACQAJADwALwBiAHUAdAB0AG8AbgA%2BAAoACQAJAAkAPABiAHUAdAB0AG8AbgAgAG8AbgBDAGwAaQBjAGsAPQB7AG8AbgBTAGUAYQByAGMAaABMAG8AYwBhAGwAMwB9ACAAdAB5AHAAZQA9ACIAYgB1AHQAdABvAG4AIgA%2BAAoACQAJAAkACQBDAGwAaQBjAGsAIABmAG8AcgAgAHMAZQBhAHIAYwBoACAAMwAKAAkACQAJADwALwBiAHUAdAB0AG8AbgA%2BAAoACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAA8AGIAdQB0AHQAbwBuACAAbwBuAEMAbABpAGMAawA9AHsAbwBuAFMAZQBhAHIAYwBoAEwAbwBjAGEAbAA0AH0AIAB0AHkAcABlAD0AIgBiAHUAdAB0AG8AbgAiAD4ACgAJAAkACQAJAEMAbABpAGMAawAgAGYAbwByACAAcwBlAGEAcgBjAGgAIAA0AAoACQAJAAkAPAAvAGIAdQB0AHQAbwBuAD4ACgAJAAkAPAAvAD4ACgAJACkAOwAKAH0A&files.package.json=

Expected result

In the file below React useCallback dependencies rule in biome is giving incorrect behaviour.

import { useState, useCallback, useContext, createContext } from "react";
import { debounce } from "lodash";
const TestContext = React.createContext();
export function Test() {
	const [q, setQ] = useState("");
	const onSearch = () => {

		console.log("searched text is", q);
	};
	return (
		<TestContext.provider value={onSearch}>
			<input
				value={q}
				onChange={(e) => {
					setQ(e.target.value);
				}}
			/>
			<MySearchBtn />
		</TestContext.provider>
	);
}

export function MySearchBtn() {
	const searchContext = useContext(TestContext);
	const { onSearch } = searchContext;

	//actual: error, expected: error -- Scenario A   ✅
	const onSearchLocal1 = useCallback(() => {
		onSearch();
	}, []);

	//actual: no error, expected: error -- Scenario B ❌
	const onSearchLocal2 = useCallback(()=>debounce(onSearch, 150), []);

	//actual: no error, expected: error -- Scenario C ❌
	const onSearchLocal3 = useCallback(onSearch, []);

    //actual: error, expected: no error -- Scenario D ❌
	const onSearchLocal4 = useCallback(onSearch, [onSearch]);


  
	return (
		<>
			<button onClick={onSearchLocal1} type="button">
				Click for search 1
			</button>
			<button onClick={onSearchLocal2} type="button">
				Click for search 2
			</button>
			<button onClick={onSearchLocal3} type="button">
				Click for search 3
			</button>

                         <button onClick={onSearchLocal4} type="button">
				Click for search 4
			</button>
		</>
	);
}

for example

In scenario-B/Scenario-C(see in code ,where I commented those line) , biome is not giving me error, As I know that useCallback hook used here depends on onSearch function, so it should give me the error/warning saying incorrect deps(bcz i missed onSearch as deps, but now I didn't get any error in that.

Instead of that, when I add the dependency onSearch into that dependencies list in scenario-D, getting This hook specifies more dependencies than necessary: onSearch, scenario-D is correct from react perspective as I add all deps, but getting the error/warning in biome.

Is it because type-aware linting is not there on biome? not sure about that.

thanks for any help in that.

Also checked in react witht he react eslint plugin eslint-plugin-react-hooks I get expected correct behavior

Code of Conduct

  • I agree to follow Biome's Code of Conduct

Metadata

Metadata

Assignees

Labels

A-LinterArea: linterD-ReactDomain: ReactL-JavaScriptLanguage: JavaScript and super languagesS-Bug-confirmedStatus: report has been confirmed as a valid bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions