fix(analysis): preserve tab panel state
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
export const useControllableState = <T,>(
|
||||
externalValue: T | undefined,
|
||||
onExternalChange: ((value: T) => void) | undefined,
|
||||
defaultValue: T,
|
||||
) => {
|
||||
const [internalValue, setInternalValue] = useState<T>(defaultValue);
|
||||
const value = externalValue !== undefined ? externalValue : internalValue;
|
||||
const valueRef = useRef(value);
|
||||
|
||||
useEffect(() => {
|
||||
valueRef.current = value;
|
||||
}, [value]);
|
||||
|
||||
const setValue = useCallback(
|
||||
(next: T | ((previous: T) => T)) => {
|
||||
const nextValue =
|
||||
typeof next === "function"
|
||||
? (next as (previous: T) => T)(valueRef.current)
|
||||
: next;
|
||||
valueRef.current = nextValue;
|
||||
if (externalValue === undefined) {
|
||||
setInternalValue(nextValue);
|
||||
}
|
||||
onExternalChange?.(nextValue);
|
||||
},
|
||||
[externalValue, onExternalChange],
|
||||
);
|
||||
|
||||
return [value, setValue] as const;
|
||||
};
|
||||
|
||||
export const useControllableObjectState = <T extends object>(
|
||||
externalValue: T | undefined,
|
||||
onExternalChange: ((value: T) => void) | undefined,
|
||||
defaultValue: T,
|
||||
) => {
|
||||
const [value, setValue] = useControllableState(
|
||||
externalValue,
|
||||
onExternalChange,
|
||||
defaultValue,
|
||||
);
|
||||
|
||||
const setField = useCallback(
|
||||
<K extends keyof T>(key: K, nextValue: T[K]) => {
|
||||
setValue((previous) => ({ ...previous, [key]: nextValue }));
|
||||
},
|
||||
[setValue],
|
||||
);
|
||||
|
||||
return [value, setValue, setField] as const;
|
||||
};
|
||||
Reference in New Issue
Block a user