Controllable State Hook
ncdai-chirags/use-controllable-stateFreeHook
ncdai publishes no description for this item.
Install it
npx shadcn@latest add https://www.chirags.dev/r/use-controllable-state.jsonSource
1/* eslint-disable @typescript-eslint/no-explicit-any */2// This code comes from https://github.com/radix-ui/primitives/blob/main/packages/react/use-controllable-state/src/use-controllable-state.tsx34import * as React from "react";56import { useLayoutEffect } from "@/hooks/use-layout-effect";78// Prevent bundlers from trying to optimize the import9const useInsertionEffect: typeof useLayoutEffect =10 (React as any)[" useInsertionEffect ".trim().toString()] || useLayoutEffect;1112type ChangeHandler<T> = (state: T) => void;13type SetStateFn<T> = React.Dispatch<React.SetStateAction<T>>;1415interface UseControllableStateParams<T> {16 prop?: T | undefined;17 defaultProp: T;18 onChange?: ChangeHandler<T>;19 caller?: string;20}2122export function useControllableState<T>({23 prop,24 defaultProp,25 onChange = () => {},26 caller,27}: UseControllableStateParams<T>): [T, SetStateFn<T>] {28 const [uncontrolledProp, setUncontrolledProp, onChangeRef] =29 useUncontrolledState({30 defaultProp,31 onChange,32 });33 const isControlled = prop !== undefined;34 const value = isControlled ? prop : uncontrolledProp;3536 // OK to disable conditionally calling hooks here because they will always run37 // consistently in the same environment. Bundlers should be able to remove the38 // code block entirely in production.39 /* eslint-disable react-hooks/rules-of-hooks */40 if (process.env.NODE_ENV !== "production") {41 const isControlledRef = React.useRef(prop !== undefined);42 React.useEffect(() => {43 const wasControlled = isControlledRef.current;44 if (wasControlled !== isControlled) {45 const from = wasControlled ? "controlled" : "uncontrolled";46 const to = isControlled ? "controlled" : "uncontrolled";47 console.warn(48 `${caller} is changing from ${from} to ${to}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`49 );50 }51 isControlledRef.current = isControlled;52 }, [isControlled, caller]);53 }54 /* eslint-enable react-hooks/rules-of-hooks */5556 const setValue = React.useCallback<SetStateFn<T>>(57 (nextValue) => {58 if (isControlled) {59 const value = isFunction(nextValue) ? nextValue(prop) : nextValue;60 if (value !== prop) {61 onChangeRef.current?.(value);62 }63 } else {64 setUncontrolledProp(nextValue);65 }66 },67// … truncated
Files it writes
More from ncdai
All 28 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Sound Hookuse-sound | ncdai | Hooks | Free | no deps |
