Skip to content
Draft
Prev Previous commit
Next Next commit
feat(lint): enable useExhaustiveDependencies rule with suppressions
Enable the biome correctness/useExhaustiveDependencies lint rule (was
previously "off"). All existing violations are suppressed with
biome-ignore comments added via `biome lint --suppress`.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01EHt5dM7Rts48s8HzcCaZCz
  • Loading branch information
claude committed Feb 23, 2026
commit bd8e6524be42d9f24c7fe8883bfce05a676e29a0
2 changes: 1 addition & 1 deletion biome.json
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all the new rules in this file already passing? Wondering how to make sense of these additions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess claude thought they are required after the upgrade to latest biome - I will rever them and see

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aha - it has a point
Screenshot 2026-02-20 at 13 20 31

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, they were all set to "off" thus effectively disabled. Makes sense.

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"noUnusedFunctionParameters": "off",
"noUnusedImports": "off",
"noUnusedVariables": "off",
"useExhaustiveDependencies": "off",
"useExhaustiveDependencies": "warn",
"useHookAtTopLevel": "off",
"useJsxKeyInIterable": "off",
"useParseIntRadix": "off"
Expand Down
1 change: 1 addition & 0 deletions src/Apps/Article/Components/ArticleHTML.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const ArticleHTML: FC<React.PropsWithChildren<ArticleHTMLProps>> = ({

const [transformed, setTransformed] = useState<string | null>(null)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
// Relies on the DOMParser global being available in the browser.
import("@artsy/react-html-parser").then(({ default: reactHtmlParser }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const Image: FC<

const ref = useRef<HTMLImageElement>(null)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (ref.current?.complete) {
setMode("Ready")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const AuctionFilterMobileActionSheet: FC<
filterContext.stagedFilters,
)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
// While mobile sheet is mounted, the effect of the user's filter selections
// should be merely staged until the Apply button is pressed, rather than
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ export const KeywordFilter: React.FC<React.PropsWithChildren<unknown>> = () => {
filterContext.setFilter?.("keyword", text)
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
const handleChangeText = useMemo(
() => debounce(updateKeywordFilter, DEBOUNCE_DELAY),
// FIXME:
[filterContext],
)

// Stop the invocation of the debounced function after unmounting
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
return () => handleChangeText?.cancel?.()
// FIXME:
}, [])
Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Artwork/ArtworkApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ export const ArtworkApp: React.FC<React.PropsWithChildren<Props>> = props => {

// If the user is expecting a partner offer, require login and remove
// the query param from the URL after login.
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
const expectingPartnerOffer = !!match?.location?.query?.partner_offer_id
const isLoggedIn = !!me

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const ArtworkErrorApp: React.FC<
}
}, [])

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
trackPageview()
}, [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ArtworkSidebarAuctionPolling: React.FC<
const isMounted = useRef(false)
const tracking = useTracking()

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (isMounted.current) {
setCurrentBidChanged(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const ArtworkVideoPlayer: FC<
}, 0)
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
window.addEventListener("blur", trackClickedPlayVideo)

Expand Down
1 change: 1 addition & 0 deletions src/Apps/Auction/AuctionApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const AuctionApp: React.FC<React.PropsWithChildren<AuctionAppProps>> = ({

const isFullBleedHeaderFixed = !cascadingEndTimeIntervalMinutes

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
tracking.auctionPageView({ sale, me })
}, [])
Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Auction/Routes/AuctionConfirmRegistrationRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const AuctionConfirmRegistrationRoute: React.FC<
}

// Track page view or redirect
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (redirectToSaleHome(sale)) {
router.replace(`/auction/${sale.slug}`)
} else if (!me.hasQualifiedCreditCards) {
Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Auction/Routes/AuctionRegistrationRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const AuctionRegistrationRoute: React.FC<
}

// Track page view or redirect
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (redirectToSaleHome(sale)) {
router.replace(`/auction/${sale.slug}`)
} else if (me.hasQualifiedCreditCards) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export const PricingTransparencyQueryRenderer = ({
// when the url changes after user places a successful bid and we redirect
// back to artwork/id. If / when we remove the transition to the auction page
// from artwork/id we can remove this hack.
const variables = useMemo(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
const variables = useMemo(() => {
return {
saleId,
artworkId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const MyCollectionArtworkFormImages: React.FC<
return photos.filter(c => !(c.geminiToken || c.url) && !c.loading)
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
const imagesToUpload = getImagesToUpload(values.newPhotos)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const MyCollectionCreateArtwork: React.FC<
}
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
window?.scrollTo?.({ top: 0 })
}, [currentStep])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ const CollectorProfileSavesRoute: FC<
* To prevent this from happening, `useMemo` is used here
*/

const selectedArtworkList = useMemo(() => {

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
const selectedArtworkList = useMemo(() => {
return artworkLists.find(
artworkList => artworkList.internalID === selectedArtworkListId,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const SavesArtworks: FC<React.PropsWithChildren<SavesArtworksProps>> = ({
)
}, [state.priceMax, state.priceMin])

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
const SaveArtworksInvalidFallback = useMemo(() => {
return ({ onReset }: ErrorFallbackProps) => {
return (
Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Components/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export const AppShell: React.FC<
// Check to see if a route has a onServerSideRender key; if so call it. Used
// typically to preload bundle-split components (import()) while the route is
// fetching data in the background.
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
try {
if (match) {
routeConfig?.onClientSideRender?.({ match })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const ArtsyGuaranteeMessage: React.FC<
const { match } = useRouter()
const [showBanner, setShowBanner] = useState(false)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
setShowBanner(true)

Expand Down
1 change: 1 addition & 0 deletions src/Apps/Conversations/components/ConversationReply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export const ConversationReply: FC<
},
)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
resetForm()
}, [data?.internalID, resetForm])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ const useAutoScrollToBottom = ({
}, [lastMessageId, triggerAutoScroll])

// Additional effect to ensure initial scroll after component mount
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (lastMessageId) {
const timeoutId = setTimeout(() => {
triggerAutoScroll({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const ConversationsSidebar: React.FC<
totalDisplayedCount = SIDEBAR_FETCH_PAGE_SIZE
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (!match.params.conversationId) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ConversationsSidebarItem: React.FC<

const shouldHighlight = isSelected || isUnread

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (isSelected) {
scrollRef.current?.scrollIntoView?.({ block: "center" })
Expand Down
1 change: 1 addition & 0 deletions src/Apps/Conversations/hooks/useLoadMore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const useLoadMore = ({
return isFunction(isLoadingNext) ? isLoadingNext() : isLoadingNext
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (shouldLoadMore && hasMore() && !isLoading() && when !== false) {
loadNext(pageSize, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const FairOrganizerDedicatedArticles: React.FC<
const [isLoading, setIsLoading] = useState(false)
const logger = createLogger("FairOrganizerDedicatedArticles.tsx")

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
setIsLoading(true)

Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Notifications/NotificationsApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const NotificationsApp: React.FC<
const isNotificationsPage = pathname.startsWith("/notifications")

// Scroll to top of content pane when route changes
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
contentRef.current?.scrollTo(0, 0)
}, [pathname])

Expand Down
4 changes: 3 additions & 1 deletion src/Apps/Order/Components/AddressVerificationFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ const AddressVerificationFlow: React.FC<
>(addressOptions[0]?.key)

// perform only once when the flow first loads
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (verificationPath === VerificationPath.ERROR_IMMEDIATE_CONFIRM) {
const fallbackOption = fallbackFromFormValues(verificationInput)
onChosenAddress(AddressVerifiedBy.USER, fallbackOption.address)
Expand Down Expand Up @@ -186,6 +187,7 @@ const AddressVerificationFlow: React.FC<
setShowModal(false)
onChosenAddress(verifiedBy, selectedAddress.address)
}
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
}, [addressOptions, onChosenAddress, selectedAddressKey])

const handleCloseModal = ({
Expand Down
2 changes: 2 additions & 0 deletions src/Apps/Order/Components/PriceOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const PriceOptions: React.FC<
selectedPriceOption,
)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (lastOffer) {
onChange(lastOffer)
Expand All @@ -71,6 +72,7 @@ export const PriceOptions: React.FC<
}
}, [])

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (toggle) trackClick("Different amount", 0)
}, [toggle])
Expand Down
1 change: 1 addition & 0 deletions src/Apps/Order/Hooks/useStripePaymentBySetupIntentId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function useStripePaymentBySetupIntentId(orderId: string) {
null,
)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
// pull necessary params from Stripe redirect URL
const {
Expand Down
1 change: 1 addition & 0 deletions src/Apps/Order/OrderApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const OrderApp: FC<React.PropsWithChildren<OrderAppProps>> = props => {

const removeNavigationListenerRef = useRef<null | (() => void)>(null)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (!removeNavigationListenerRef.current) {
removeNavigationListenerRef.current =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const OrderDetailsPage = ({ order, me }: OrderDetailsPageProps) => {
const meData = useFragment(ME_FRAGMENT, me)
const tracking = useOrder2Tracking(orderData.source, orderData.mode)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (!!orderData) {
tracking.orderDetailsViewed(
Expand Down
9 changes: 7 additions & 2 deletions src/Apps/Order/Routes/Payment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const PaymentRoute: FC<

const artworkVersion = extractNodes(order.lineItems)[0]?.artworkVersion

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
const bankAccountsArray =
selectedPaymentMethod !== "SEPA_DEBIT"
Expand All @@ -121,6 +122,7 @@ export const PaymentRoute: FC<
}
}, [order])

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
setSelectedPaymentMethod(getInitialPaymentMethodValue(order))
}, [order])
Expand Down Expand Up @@ -360,7 +362,8 @@ export const PaymentRoute: FC<
}

// complete payment when balance check is disabled and bank account is set
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (
!balanceCheckEnabled &&
(selectedBankAccountId || isPaymentSetupSuccessful) &&
Expand All @@ -377,7 +380,8 @@ export const PaymentRoute: FC<
])

// show error modal when payment setup error is set
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (paymentSetupError) {
let title = "An error occurred"
let message =
Expand Down Expand Up @@ -453,6 +457,7 @@ export const PaymentRoute: FC<
})
}

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (order && me) {
setIsLoading(false)
Expand Down
3 changes: 2 additions & 1 deletion src/Apps/Order/Routes/Shipping/Components/AddressModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ const AddressModalForm: FC<
addressModalAction.type === "edit" ? Object.keys(errors.address || {}) : []

// Touch fields that have errors on edit
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (attributeErrorFieldsForEdit.length > 0) {
attributeErrorFieldsForEdit.forEach(field => {
setFieldTouched(`attributes.${field}`, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ export const FulfillmentDetails: FC<
* the rest of its life and reset values
*/

useEffect(() => {

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
const formLoaded =
typeof shippingContext.state.fulfillmentDetailsFormikContext.setValues ===
"function"
Expand Down Expand Up @@ -95,7 +97,9 @@ export const FulfillmentDetails: FC<
* require artsy shipping
*/

useEffect(() => {

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
const { savedFulfillmentDetails } = shippingContext.orderData

const isArtsyShippingSaved =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ const FulfillmentDetailsFormLayout = (
* via `shippingContext.state.fulfillmentDetailsCtx`
*/

useEffect(() => {

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
shippingContext.actions.setFulfillmentDetailsFormikContext(formikContext)
}, [formikContext.values, formikContext.isValid])

Expand All @@ -137,6 +139,7 @@ const FulfillmentDetailsFormLayout = (

const serializedValues = JSON.stringify(formikContext.values)

// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
const handleSelectSavedAddress = useCallback(
(address: SavedAddressType) => {
shippingContext.actions.setStage("fulfillment_details")
Expand All @@ -157,7 +160,8 @@ const FulfillmentDetailsFormLayout = (
)

// Use useEffect to submit the form after values are updated
useEffect(() => {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignored using `--suppress`
useEffect(() => {
if (shouldSubmit) {
formikContext.submitForm()
setShouldSubmit(false) // Reset the state after submission
Expand Down
Loading