chore: simplify useSetting to not rely on useSyncExternalStore (#32018)

This commit is contained in:
Pavel Feldman 2024-08-06 14:30:15 -07:00 committed by GitHub
parent 7f60f284c6
commit 79ca3f28c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 18 deletions

View File

@ -43,12 +43,8 @@ export const SplitView: React.FC<SplitViewProps> = ({
main,
}) => {
const defaultSize = Math.max(minSidebarSize, sidebarSize) * window.devicePixelRatio;
const hSetting = useSetting<number>((settingName ?? 'unused') + '.' + orientation + ':size', defaultSize);
const vSetting = useSetting<number>((settingName ?? 'unused') + '.' + orientation + ':size', defaultSize);
const hState = React.useState(defaultSize);
const vState = React.useState(defaultSize);
const [hSize, setHSize] = settingName ? hSetting : hState;
const [vSize, setVSize] = settingName ? vSetting : vState;
const [hSize, setHSize] = useSetting<number>(settingName ? settingName + '.' + orientation + ':size' : undefined, defaultSize);
const [vSize, setVSize] = useSetting<number>(settingName ? settingName + '.' + orientation + ':size' : undefined, defaultSize);
const [resizing, setResizing] = React.useState<{ offset: number, size: number } | null>(null);
const [measure, ref] = useMeasure<HTMLDivElement>();
@ -80,8 +76,8 @@ export const SplitView: React.FC<SplitViewProps> = ({
return <div className={clsx('split-view', orientation, sidebarIsFirst && 'sidebar-first')} ref={ref}>
<div className='split-view-main'>{main}</div>
{ !sidebarHidden && <div style={{ flexBasis: size }} className='split-view-sidebar'>{sidebar}</div> }
{ !sidebarHidden && <div
{!sidebarHidden && <div style={{ flexBasis: size }} className='split-view-sidebar'>{sidebar}</div>}
{!sidebarHidden && <div
style={resizerStyle}
className='split-view-resizer'
onMouseDown={event => setResizing({ offset: orientation === 'vertical' ? event.clientY : event.clientX, size })}
@ -103,6 +99,6 @@ export const SplitView: React.FC<SplitViewProps> = ({
setHSize(size * window.devicePixelRatio);
}
}}
></div> }
></div>}
</div>;
};

View File

@ -141,17 +141,25 @@ export function copy(text: string) {
export type Setting<T> = readonly [T, (value: T) => void, string];
export function useSetting<S>(name: string, defaultValue: S, title?: string): [S, (v: S) => void, Setting<S>] {
const subscribe = React.useCallback((onStoreChange: () => void) => {
settings.onChangeEmitter.addEventListener(name, onStoreChange);
return () => settings.onChangeEmitter.removeEventListener(name, onStoreChange);
}, [name]);
const value = React.useSyncExternalStore(subscribe, () => settings.getObject(name, defaultValue));
export function useSetting<S>(name: string | undefined, defaultValue: S, title?: string): [S, React.Dispatch<React.SetStateAction<S>>, Setting<S>] {
if (name)
defaultValue = settings.getObject(name, defaultValue);
const [value, setValue] = React.useState<S>(defaultValue);
const setValueWrapper = React.useCallback((value: React.SetStateAction<S>) => {
if (name)
settings.setObject(name, value);
else
setValue(value);
}, [name, setValue]);
const setValueWrapper = React.useCallback((value: S) => {
settings.setObject(name, value);
}, [name]);
React.useEffect(() => {
if (name) {
const onStoreChange = () => setValue(settings.getObject(name, defaultValue));
settings.onChangeEmitter.addEventListener(name, onStoreChange);
return () => settings.onChangeEmitter.removeEventListener(name, onStoreChange);
}
}, [defaultValue, name]);
const setting = [value, setValueWrapper, title || name || ''] as Setting<S>;
return [value, setValueWrapper, setting];