Skip to content

Commit 7e6d8be

Browse files
committed
WIP
1 parent db97743 commit 7e6d8be

5 files changed

Lines changed: 39 additions & 121 deletions

File tree

plugins/ui/src/js/src/elements/UITable/UITable.tsx

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import {
1414
type IrisGridContextMenuData,
1515
IrisGridProps,
1616
IrisGridUtils,
17+
IrisGridCacheUtils,
1718
IrisGridState,
18-
DehydratedIrisGridState,
19+
type DehydratedIrisGridState,
20+
type DehydratedGridState,
1921
} from '@deephaven/iris-grid';
2022
import {
2123
ColorValues,
@@ -30,8 +32,9 @@ import { TableUtils } from '@deephaven/jsapi-utils';
3032
import type { dh as DhType } from '@deephaven/jsapi-types';
3133
import Log from '@deephaven/log';
3234
import { getSettings, RootState } from '@deephaven/redux';
33-
import { GridMouseHandler } from '@deephaven/grid';
35+
import { GridMouseHandler, GridState } from '@deephaven/grid';
3436
import { EMPTY_ARRAY, ensureArray } from '@deephaven/utils';
37+
import { usePersistentState } from '@deephaven/plugin';
3538
import {
3639
DatabarConfig,
3740
FormattingRule,
@@ -45,7 +48,6 @@ import UITableContextMenuHandler, {
4548
} from './UITableContextMenuHandler';
4649
import UITableModel, { makeUiTableModel } from './UITableModel';
4750
import { UITableLayoutHints } from './JsTableProxy';
48-
import usePersistentState from '../hooks/usePersistentState';
4951

5052
const log = Log.module('@deephaven/js-plugin-ui/UITable');
5153

@@ -176,8 +178,6 @@ export function UITable({
176178
databars = EMPTY_ARRAY as unknown as DatabarConfig[],
177179
...userStyleProps
178180
}: UITableProps): JSX.Element | null {
179-
const id = useMemo(() => Math.random().toString(36).substr(2, 9), []);
180-
console.log('render table', id);
181181
const [throwError] = useThrowError();
182182

183183
// Margin looks wrong with ui.table, so we want to map margin to padding instead
@@ -286,40 +286,32 @@ export function UITable({
286286
model.setColorMap(colorMap);
287287
}
288288

289-
const prevState = useRef<IrisGridState | undefined>();
290289
const [dehydratedState, setDehydratedState] = usePersistentState<
291-
DehydratedIrisGridState | undefined
292-
>(undefined);
290+
(DehydratedIrisGridState & DehydratedGridState) | undefined
291+
>(undefined, { type: 'UITable', version: 1 });
293292
const initialState = useRef(dehydratedState);
294293

294+
const memoizedStateFn = useMemo(
295+
() => IrisGridCacheUtils.makeMemoizedCombinedGridStateDehydrator(),
296+
[]
297+
);
298+
295299
const onStateChange = useCallback(
296-
(newState: IrisGridState) => {
297-
if (
298-
model == null ||
299-
newState.metrics == null ||
300-
newState === prevState.current ||
301-
newState.sorts === prevState.current?.sorts
302-
) {
300+
(irisGridState: IrisGridState, gridState: GridState) => {
301+
if (model == null) {
303302
return;
304303
}
305-
// console.log('onStateChange', newState);
306-
prevState.current = newState;
307-
setDehydratedState(
308-
utils.dehydrateIrisGridState(model, {
309-
...newState,
310-
metrics: {
311-
userColumnWidths: newState.metrics.userColumnWidths,
312-
userRowHeights: newState.metrics.userRowHeights,
313-
},
314-
})
315-
);
304+
setDehydratedState(memoizedStateFn(model, irisGridState, gridState));
316305
},
317-
[model, setDehydratedState, utils]
306+
[memoizedStateFn, model, setDehydratedState]
318307
);
319308

320-
const hydratedState = useMemo(() => {
321-
if (model && initialState.current) {
322-
return utils.hydrateIrisGridState(model, initialState.current);
309+
const initialHydratedState = useMemo(() => {
310+
if (model && initialState.current != null) {
311+
return {
312+
...utils.hydrateIrisGridState(model, initialState.current),
313+
...IrisGridUtils.hydrateGridState(model, initialState.current),
314+
};
323315
}
324316
}, [model, utils]);
325317

@@ -521,7 +513,7 @@ export function UITable({
521513
model={model}
522514
onStateChange={onStateChange}
523515
// eslint-disable-next-line react/jsx-props-no-spreading
524-
{...hydratedState}
516+
{...initialHydratedState}
525517
// eslint-disable-next-line react/jsx-props-no-spreading
526518
{...irisGridProps}
527519
/>

plugins/ui/src/js/src/elements/hooks/usePersistentState.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

plugins/ui/src/js/src/layout/ReactPanel.tsx

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
LoadingOverlay,
2222
} from '@deephaven/components';
2323
import Log from '@deephaven/log';
24+
import { PersistentStateProvider } from '@deephaven/plugin';
2425
import PortalPanel from './PortalPanel';
2526
import { ReactPanelControl, useReactPanel } from './ReactPanelManager';
2627
import { ReactPanelProps } from './LayoutUtils';
@@ -208,50 +209,9 @@ function ReactPanel({
208209
renderedChildren = children;
209210
}
210211

211-
const [render, setRender] = useState(0);
212-
213-
const persistentData = useRef({
214-
initial: getInitialData(),
215-
prev: [] as unknown[],
216-
next: [] as unknown[],
217-
});
218-
219-
console.log('panel render', renderedChildren);
220-
221-
const panelContextValue = useMemo(
222-
() => ({
223-
panelId,
224-
addPanelState(state: unknown) {
225-
persistentData.current.next.push(state);
226-
},
227-
initialStateIterator: persistentData.current.initial[Symbol.iterator](),
228-
getInitialState() {
229-
// eslint-disable-next-line react/no-this-in-sfc
230-
const { value, done } = this.initialStateIterator.next();
231-
return value;
232-
},
233-
trigger() {
234-
persistentData.current.next = [];
235-
// eslint-disable-next-line react/no-this-in-sfc
236-
this.isTracking = true;
237-
setRender(prev => prev + 1);
238-
},
239-
isTracking: false,
240-
}),
241-
[panelId]
242-
);
243-
244-
useEffect(() => {
245-
console.log('panel effect', persistentData.current.next.length);
246-
persistentData.current.prev = persistentData.current.next;
247-
persistentData.current.next = [];
248-
panelContextValue.isTracking = false;
249-
onDataChange(persistentData.current.prev);
250-
}, [render, panelContextValue, onDataChange]);
251-
252212
return portal
253213
? ReactDOM.createPortal(
254-
<ReactPanelContext.Provider value={panelContextValue}>
214+
<ReactPanelContext.Provider value={panelId}>
255215
<View
256216
height="100%"
257217
width="100%"
@@ -287,9 +247,14 @@ function ReactPanel({
287247
* Don't render the children if there's an error with the widget. If there's an error with the widget, we can assume the children won't render properly,
288248
* but we still want the panels to appear so things don't disappear/jump around.
289249
*/}
290-
{React.Children.map(renderedChildren, child =>
291-
React.cloneElement(child as React.ReactElement)
292-
)}
250+
<PersistentStateProvider
251+
initialState={getInitialData()}
252+
onChange={onDataChange}
253+
>
254+
{React.Children.map(renderedChildren, child =>
255+
React.cloneElement(child as React.ReactElement)
256+
)}
257+
</PersistentStateProvider>
293258
</ReactPanelErrorBoundary>
294259
</Flex>
295260
</View>
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
import { createContext, useContext } from 'react';
22

3-
type PanelContextType = {
4-
panelId: string;
5-
addPanelState: (state: unknown) => void;
6-
trigger: () => void;
7-
isTracking: boolean;
8-
getInitialState: () => unknown;
9-
};
10-
113
/**
124
* Context that holds the ID of the panel that we are currently in.
135
*/
14-
export const ReactPanelContext = createContext<PanelContextType | null>(null);
6+
export const ReactPanelContext = createContext<string | null>(null);
157

168
/**
179
* Gets the panel ID from the nearest panel context.
1810
* @returns The panel ID or null if not in a panel
1911
*/
2012
export function usePanelId(): string | null {
21-
return useContext(ReactPanelContext)?.panelId ?? null;
13+
return useContext(ReactPanelContext);
2214
}

plugins/ui/src/js/src/widget/DocumentHandler.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import React, {
88
import { nanoid } from 'nanoid';
99
import { WidgetDescriptor } from '@deephaven/dashboard';
1010
import Log from '@deephaven/log';
11-
import { EMPTY_FUNCTION } from '@deephaven/utils';
11+
import { EMPTY_ARRAY, EMPTY_FUNCTION } from '@deephaven/utils';
1212
import { ReactPanelManagerContext } from '../layout/ReactPanelManager';
1313
import { getRootChildren } from './DocumentUtils';
1414
import {
@@ -150,7 +150,9 @@ function DocumentHandler({
150150
}, [widgetData]);
151151

152152
const getInitialData = useCallback(
153-
(panelId: string) => widgetData.panelStates?.[panelId] ?? [],
153+
(panelId: string) =>
154+
widgetData.panelStates?.[panelId] ??
155+
(EMPTY_ARRAY as unknown as unknown[]),
154156
[widgetData]
155157
);
156158

0 commit comments

Comments
 (0)