Skip to content

Commit

Permalink
Fixes #216
Browse files Browse the repository at this point in the history
  • Loading branch information
radubrehar committed Feb 21, 2024
1 parent ed538df commit bf0443f
Show file tree
Hide file tree
Showing 19 changed files with 221 additions and 60 deletions.
19 changes: 14 additions & 5 deletions examples/src/pages/tests/table/master-detail/default.page.tsx
Expand Up @@ -74,10 +74,12 @@ const dataSource = () => {
const detailDataSource: DataSourceProps<Developer>['data'] = ({
sortInfo,
filterValue,
masterRowInfo,
}) => {
if (sortInfo && !Array.isArray(sortInfo)) {
sortInfo = [sortInfo];
}
console.log(masterRowInfo?.data, 'master');

const args = [
filterValue
Expand Down Expand Up @@ -157,7 +159,7 @@ export default function DataTestPage() {
collapsedRows: true,
}}
rowDetailHeight={400}
rowDetailsCache={3}
rowDetailsCache={false}
rowDetailRenderer={(
rowInfo: InfiniteTableRowInfo<Developer>,
_cache,
Expand All @@ -174,12 +176,19 @@ export default function DataTestPage() {
>
<form style={{ padding: 20 }}>
<label>
Name:
<input />
First name:
<input
name="first name"
defaultValue={rowInfo.data?.firstName}
/>
</label>
<label>
Name:
<input />
Age:
<input
name="last name"
type="number"
defaultValue={rowInfo.data?.age}
/>
</label>
</form>
<DataSource<Developer>
Expand Down
1 change: 1 addition & 0 deletions source/src/components/DataSource/DataSourceContext.ts
Expand Up @@ -16,6 +16,7 @@ export function getDataSourceContext<T>(): React.Context<
api: null as any as DataSourceApi<T>,
getState: () => null as any as DataSourceState<T>,
assignState: () => null as any as DataSourceState<T>,
getDataSourceMasterContext: () => undefined,
componentState: null as any as DataSourceState<T>,
componentActions: null as any as DataSourceComponentActions<T>,
}));
Expand Down
5 changes: 5 additions & 0 deletions source/src/components/DataSource/index.tsx
Expand Up @@ -85,10 +85,14 @@ function DataSourceCmp<T>({
const DataSourceContext = getDataSourceContext<T>();

const masterContext = useMasterDetailContext();
const getDataSourceMasterContext = useLatest(masterContext);

const { componentState, componentActions, assignState } =
useComponentState<DataSourceState<T>>();

componentState.getDataSourceMasterContextRef.current =
getDataSourceMasterContext;

const getState = useLatest(componentState);

const [api] = React.useState(() => {
Expand All @@ -97,6 +101,7 @@ function DataSourceCmp<T>({
const contextValue: DataSourceContextValue<T> = {
componentState,
componentActions,
getDataSourceMasterContext,
getState,
assignState,
api,
Expand Down
97 changes: 74 additions & 23 deletions source/src/components/DataSource/privateHooks/useLoadData.ts
@@ -1,12 +1,17 @@
import { useEffect, useMemo, useRef, useState } from 'react';

import { LazyGroupDataItem, LazyRowInfoGroup } from '..';
import {
DataSourceMasterDetailContextValue,
LazyGroupDataItem,
LazyRowInfoGroup,
} from '..';
import { DeepMap } from '../../../utils/DeepMap';
import { LAZY_ROOT_KEY_FOR_GROUPS } from '../../../utils/groupAndPivot';
import { raf } from '../../../utils/raf';
import { useComponentState } from '../../hooks/useComponentState';
import { ComponentStateGeneratedActions } from '../../hooks/useComponentState/types';
import { useEffectWithChanges } from '../../hooks/useEffectWithChanges';
import { useLatest } from '../../hooks/useLatest';
import { Scrollbars } from '../../InfiniteTable';
import { assignExcept } from '../../InfiniteTable/utils/assignFiltered';
import { debounce } from '../../utils/debounce';
Expand Down Expand Up @@ -50,6 +55,7 @@ const DATA_CHANGES_COMPARE_FUNCTIONS: Record<
export function buildDataSourceDataParams<T>(
componentState: DataSourceState<T>,
overrides?: Partial<DataSourceDataParams<T>>,
masterContext?: DataSourceMasterDetailContextValue,
): DataSourceDataParams<T> {
const sortInfo = componentState.multiSort
? componentState.sortInfo
Expand All @@ -66,6 +72,10 @@ export function buildDataSourceDataParams<T>(
aggregationReducers: componentState.aggregationReducers,
};

if (masterContext) {
dataSourceParams.masterRowInfo = masterContext.masterRowInfo;
}

if (dataSourceParams.groupBy) {
dataSourceParams.groupRowsState = componentState.groupRowsState.getState();
}
Expand Down Expand Up @@ -135,8 +145,13 @@ export function loadData<T>(
componentState: DataSourceState<T>,
actions: ComponentStateGeneratedActions<DataSourceState<T>>,
overrides?: Partial<DataSourceDataParams<T>>,
masterContext?: DataSourceMasterDetailContextValue | undefined,
) {
const dataParams = buildDataSourceDataParams(componentState, overrides);
const dataParams = buildDataSourceDataParams(
componentState,
overrides,
masterContext,
);
const append = dataParams.append;

if (componentState.lazyLoad) {
Expand Down Expand Up @@ -396,6 +411,26 @@ function computeFilterValueForRemote<T>(
);
}

function getDetailReady(
masterContext: DataSourceMasterDetailContextValue | undefined,
getDataSourceState: () => DataSourceState<any>,
) {
const isDetail = !!masterContext;

const { stateReadyAsDetails } = getDataSourceState();

const isDetailReady = isDetail
? masterContext.shouldRestoreState
? stateReadyAsDetails
: true
: true;

return {
isDetail,
isDetailReady,
};
}

export function useLoadData<T>() {
const {
getComponentState,
Expand All @@ -418,7 +453,6 @@ export function useLoadData<T>() {
livePaginationCursor,
filterTypes,
cursorId: stateCursorId,
stateReadyAsDetails,
} = componentState;

const [scrollbars, setScrollbars] = useState<Scrollbars>({
Expand Down Expand Up @@ -527,29 +561,30 @@ export function useLoadData<T>() {

useLazyLoadRange<T>();

const masterContext = useMasterDetailContext();

const isDetail = !!masterContext;
const isDetailRef = useRef(!!masterContext);
isDetailRef.current = isDetail;

const isDetailReady = isDetail
? masterContext.shouldRestoreState
? stateReadyAsDetails
: true
: true;
const isDetailReadyRef = useRef(isDetailReady);
isDetailReadyRef.current = isDetailReady;
const getMasterContext = useLatest(useMasterDetailContext());

useEffectWithChanges(
() => {
const componentState = getComponentState();
if (isDetailRef.current && !isDetailReadyRef.current) {

const masterContext = getMasterContext();

const { isDetail, isDetailReady } = getDetailReady(
masterContext,
getComponentState,
);
if (isDetail && !isDetailReady) {
return;
}

if (typeof componentState.data !== 'function') {
loadData(componentState.data, componentState, actions);
loadData(
componentState.data,
componentState,
actions,
undefined,
masterContext,
);
}
},
{ data },
Expand All @@ -570,15 +605,27 @@ export function useLoadData<T>() {
}
}

if (isDetailRef.current && !isDetailReadyRef.current) {
const masterContext = getMasterContext();
const { isDetail, isDetailReady } = getDetailReady(
masterContext,
getComponentState,
);

if (isDetail && !isDetailReady) {
return;
}

const componentState = getComponentState();
if (typeof componentState.data === 'function') {
loadData(componentState.data, componentState, actions, {
append: appendWhenLivePagination,
});
loadData(
componentState.data,
componentState,
actions,
{
append: appendWhenLivePagination,
},
masterContext,
);
}
},
{ ...depsObject, data },
Expand All @@ -590,7 +637,11 @@ export function useLoadData<T>() {
if (initialRef.current) {
initialRef.current = false;

const dataParams = buildDataSourceDataParams(componentState);
const dataParams = buildDataSourceDataParams(
componentState,
undefined,
getMasterContext(),
);
actions.dataParams = dataParams;
}
}, depsObject);
Expand Down
83 changes: 61 additions & 22 deletions source/src/components/DataSource/state/getInitialState.ts
Expand Up @@ -68,6 +68,8 @@ export function initSetupState<T>(): DataSourceSetupState<T> {

idToIndexMap: new Map<any, number>(),

getDataSourceMasterContextRef: { current: () => undefined },

// TODO: cleanup cache on unmount
cache: undefined,
detailDataSourcesStateToRestore: new Map(),
Expand Down Expand Up @@ -498,10 +500,16 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
> {
return {
sortInfo: (sortInfo, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
sortInfo,
livePaginationCursor: null,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
sortInfo,
livePaginationCursor: null,
},
getDataSourceMasterContext(),
);

actions.dataParams = dataParams;

Expand All @@ -515,10 +523,16 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
}
},
groupBy: (groupBy, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
groupBy,
livePaginationCursor: null,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
groupBy,
livePaginationCursor: null,
},
getDataSourceMasterContext(),
);

actions.dataParams = dataParams;

Expand All @@ -531,10 +545,16 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
}
},
pivotBy: (pivotBy, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
pivotBy,
livePaginationCursor: null,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
pivotBy,
livePaginationCursor: null,
},
getDataSourceMasterContext(),
);

actions.dataParams = dataParams;

Expand All @@ -547,10 +567,16 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
}
},
filterValue: (filterValue, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
filterValue,
livePaginationCursor: null,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
filterValue,
livePaginationCursor: null,
},
getDataSourceMasterContext(),
);

actions.dataParams = dataParams;

Expand All @@ -563,15 +589,27 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
}
},
cursorId: (cursorId, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
__cursorId: cursorId,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
__cursorId: cursorId,
},
getDataSourceMasterContext(),
);
actions.dataParams = dataParams;
},
livePaginationCursor: (livePaginationCursor, { actions, state }) => {
const dataParams = buildDataSourceDataParams(state, {
livePaginationCursor,
});
const getDataSourceMasterContext =
state.getDataSourceMasterContextRef.current;
const dataParams = buildDataSourceDataParams(
state,
{
livePaginationCursor,
},
getDataSourceMasterContext(),
);

actions.dataParams = dataParams;
},
Expand All @@ -583,6 +621,7 @@ export function getInterceptActions<T>(): ComponentInterceptedActions<
new Set<keyof DataSourceDataParams<T>>([
'changes',
'originalDataArray',
'masterRowInfo',
]),
)
) {
Expand Down

0 comments on commit bf0443f

Please sign in to comment.