UNPKG

uncontrollable

Version:

Wrap a controlled react component, to allow specific prop/handler pairs to be uncontrolled

42 lines (41 loc) 1.37 kB
import { useCallback, useRef, useState } from 'react'; export function defaultKey(key) { return 'default' + key.charAt(0).toUpperCase() + key.substr(1); } function useUncontrolledProp(propValue, defaultValue, handler) { const wasPropRef = useRef(propValue !== undefined); const [stateValue, setState] = useState(defaultValue); const isProp = propValue !== undefined; const wasProp = wasPropRef.current; wasPropRef.current = isProp; /** * If a prop switches from controlled to Uncontrolled * reset its value to the defaultValue */ if (!isProp && wasProp && stateValue !== defaultValue) { setState(defaultValue); } return [isProp ? propValue : stateValue, useCallback((...args) => { const [value, ...rest] = args; let returnValue = handler?.(value, ...rest); setState(value); return returnValue; }, [handler])]; } export { useUncontrolledProp }; export function useUncontrolled(props, config) { return Object.keys(config).reduce((result, fieldName) => { const { [defaultKey(fieldName)]: defaultValue, [fieldName]: propsValue, ...rest } = result; const handlerName = config[fieldName]; const [value, handler] = useUncontrolledProp(propsValue, defaultValue, props[handlerName]); return { ...rest, [fieldName]: value, [handlerName]: handler }; }, props); }