From 26ebf271b398374aecd3668375dc8de9881c02e0 Mon Sep 17 00:00:00 2001 From: Vasilen Kondakov Date: Sat, 21 Mar 2026 16:56:43 +0200 Subject: [PATCH] refactor: remove derived state useEffects from Carousel and Disclosure - Removed redundant `useEffect` hooks used for state syncing - Refactored [Carousel] to pass the correct active index down to the provider, eliminating duplicated state. - Refactored [Disclosure] to properly handle controlled and uncontrolled modes using an `isControlled` check during render. - Zero changes to the public API; all existing consumption works exactly the same. --- components/core/carousel.tsx | 22 ++++++---------------- components/core/disclosure.tsx | 24 +++++++++++++----------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/components/core/carousel.tsx b/components/core/carousel.tsx index 1e4210a..be2b2c8 100644 --- a/components/core/carousel.tsx +++ b/components/core/carousel.tsx @@ -34,34 +34,24 @@ function useCarousel() { export type CarouselProviderProps = { children: ReactNode; - initialIndex?: number; - onIndexChange?: (newIndex: number) => void; + index: number; + onIndexChange: (newIndex: number) => void; disableDrag?: boolean; }; function CarouselProvider({ children, - initialIndex = 0, + index, onIndexChange, disableDrag = false, }: CarouselProviderProps) { - const [index, setIndex] = useState(initialIndex); const [itemsCount, setItemsCount] = useState(0); - const handleSetIndex = (newIndex: number) => { - setIndex(newIndex); - onIndexChange?.(newIndex); - }; - - useEffect(() => { - setIndex(initialIndex); - }, [initialIndex]); - return ( @@ -129,7 +119,7 @@ function CarouselNavigation({ return (
diff --git a/components/core/disclosure.tsx b/components/core/disclosure.tsx index b6edec9..d416b6d 100644 --- a/components/core/disclosure.tsx +++ b/components/core/disclosure.tsx @@ -8,7 +8,7 @@ import { Variant, Variants, } from 'motion/react'; -import { createContext, useContext, useState, useId, useEffect } from 'react'; +import { createContext, useContext, useState, useId } from 'react'; import { cn } from '@/lib/utils'; export type DisclosureContextType = { @@ -23,7 +23,7 @@ const DisclosureContext = createContext( export type DisclosureProviderProps = { children: React.ReactNode; - open: boolean; + open?: boolean; onOpenChange?: (open: boolean) => void; variants?: { expanded: Variant; collapsed: Variant }; }; @@ -34,15 +34,17 @@ function DisclosureProvider({ onOpenChange, variants, }: DisclosureProviderProps) { - const [internalOpenValue, setInternalOpenValue] = useState(openProp); - - useEffect(() => { - setInternalOpenValue(openProp); - }, [openProp]); + const [internalOpenValue, setInternalOpenValue] = useState(false); + const isControlled = openProp !== undefined; + const open = isControlled ? openProp : internalOpenValue; const toggle = () => { - const newOpen = !internalOpenValue; - setInternalOpenValue(newOpen); + const newOpen = !open; + + if (!isControlled) { + setInternalOpenValue(newOpen); + } + if (onOpenChange) { onOpenChange(newOpen); } @@ -51,7 +53,7 @@ function DisclosureProvider({ return (