Test ag-grid optimization approach
This commit is contained in:
parent
8b57f6fdb1
commit
2c28c9dd2d
@ -62,7 +62,7 @@ interface UseMarkets {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useMarkets = (): UseMarkets => {
|
export const useMarkets = (updateCallback?: (data: MarketDataSub_marketData) => void): UseMarkets => {
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const [markets, setMarkets] = useState<Markets_markets[]>([]);
|
const [markets, setMarkets] = useState<Markets_markets[]>([]);
|
||||||
const [error, setError] = useState<Error | null>(null);
|
const [error, setError] = useState<Error | null>(null);
|
||||||
@ -81,26 +81,21 @@ export const useMarkets = (): UseMarkets => {
|
|||||||
|
|
||||||
// Make initial fetch
|
// Make initial fetch
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchOrders = async () => {
|
(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await client.query<Markets>({
|
const res = await client.query<Markets>({
|
||||||
query: MARKETS_QUERY,
|
query: MARKETS_QUERY,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.data.markets?.length) return;
|
if (!res.data.markets?.length) return;
|
||||||
|
|
||||||
setMarkets(res.data.markets);
|
setMarkets(res.data.markets);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err);
|
setError(err);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
})();
|
||||||
|
}, [client]);
|
||||||
fetchOrders();
|
|
||||||
}, [mergeMarketData, client]);
|
|
||||||
|
|
||||||
// Start subscription
|
// Start subscription
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -111,6 +106,9 @@ export const useMarkets = (): UseMarkets => {
|
|||||||
query: MARKET_DATA_SUB,
|
query: MARKET_DATA_SUB,
|
||||||
})
|
})
|
||||||
.subscribe(({ data }) => {
|
.subscribe(({ data }) => {
|
||||||
|
if (updateCallback) {
|
||||||
|
updateCallback(data.marketData);
|
||||||
|
}
|
||||||
mergeMarketData(data.marketData);
|
mergeMarketData(data.marketData);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -119,7 +117,7 @@ export const useMarkets = (): UseMarkets => {
|
|||||||
sub.unsubscribe();
|
sub.unsubscribe();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [client, mergeMarketData]);
|
}, [client, mergeMarketData, updateCallback]);
|
||||||
|
|
||||||
return { markets, error, loading };
|
return { markets, error, loading };
|
||||||
};
|
};
|
||||||
|
@ -4,14 +4,68 @@ import {
|
|||||||
Callout,
|
Callout,
|
||||||
Intent,
|
Intent,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { GridApi } from 'ag-grid-community';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
import { useApplyGridTransaction } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export function Index() {
|
const Grid = () => {
|
||||||
const rowData = [
|
const rowData = [
|
||||||
{ make: 'Toyota', model: 'Celica', price: 35000 },
|
{ make: 'Toyota', model: 'Celica', price: 35000 },
|
||||||
{ make: 'Ford', model: 'Mondeo', price: 32000 },
|
{ make: 'Ford', model: 'Mondeo', price: 32000 },
|
||||||
{ make: 'Porsche', model: 'Boxter', price: 72000 },
|
{ make: 'Porsche', model: 'Boxter', price: 72000 },
|
||||||
];
|
];
|
||||||
|
const ref = useRef(rowData);
|
||||||
|
const getRowNodeId = (data: { make: string }) => data.make;
|
||||||
|
const gridApi = useRef<GridApi | null>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (!gridApi) return;
|
||||||
|
const update = [];
|
||||||
|
const add = [];
|
||||||
|
|
||||||
|
// split into updates and adds
|
||||||
|
[...rowData].forEach((data) => {
|
||||||
|
if (!gridApi.current) return;
|
||||||
|
|
||||||
|
const rowNode = gridApi.current.getRowNode(getRowNodeId(data));
|
||||||
|
|
||||||
|
if (rowNode) {
|
||||||
|
if (rowNode.data !== data) {
|
||||||
|
update.push(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add.push(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// async transaction for optimal handling of high grequency updates
|
||||||
|
if (update.length || add.length) {
|
||||||
|
gridApi.current.applyTransaction({
|
||||||
|
update,
|
||||||
|
add,
|
||||||
|
addIndex: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<AgGrid
|
||||||
|
onGridReady={(params) => {
|
||||||
|
gridApi.current = params.api;
|
||||||
|
}}
|
||||||
|
getRowNodeId={getRowNodeId}
|
||||||
|
rowData={ref.current}
|
||||||
|
style={{ height: 400, width: 600 }}
|
||||||
|
>
|
||||||
|
<AgGridColumn field="make"></AgGridColumn>
|
||||||
|
<AgGridColumn field="model"></AgGridColumn>
|
||||||
|
<AgGridColumn field="price"></AgGridColumn>
|
||||||
|
</AgGrid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Index() {
|
||||||
return (
|
return (
|
||||||
<div className="m-24">
|
<div className="m-24">
|
||||||
<div className="mb-24">
|
<div className="mb-24">
|
||||||
@ -29,11 +83,7 @@ export function Index() {
|
|||||||
</div>
|
</div>
|
||||||
</Callout>
|
</Callout>
|
||||||
</div>
|
</div>
|
||||||
<AgGrid rowData={rowData} style={{ height: 400, width: 600 }}>
|
<Grid />
|
||||||
<AgGridColumn field="make"></AgGridColumn>
|
|
||||||
<AgGridColumn field="model"></AgGridColumn>
|
|
||||||
<AgGridColumn field="price"></AgGridColumn>
|
|
||||||
</AgGrid>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@ import { useRouter } from 'next/router';
|
|||||||
import { MarketListTable } from '@vegaprotocol/market-list';
|
import { MarketListTable } from '@vegaprotocol/market-list';
|
||||||
import { useMarkets } from '../../hooks/use-markets';
|
import { useMarkets } from '../../hooks/use-markets';
|
||||||
import { AsyncRenderer } from '../../components/async-renderer';
|
import { AsyncRenderer } from '../../components/async-renderer';
|
||||||
|
import { updateCallback } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const Markets = () => {
|
const Markets = () => {
|
||||||
const { pathname, push } = useRouter();
|
const { pathname, push } = useRouter();
|
||||||
const { markets, error, loading } = useMarkets();
|
const { markets, error, loading } = useMarkets(updateCallback);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer loading={loading} error={error} data={markets}>
|
<AsyncRenderer loading={loading} error={error} data={markets}>
|
||||||
@ -22,6 +23,15 @@ const Markets = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TwoMarkets = () => (<><div style={{height: '50%'}}><Markets /></div><div style={{height: '50%'}}><Markets /></div></>)
|
const TwoMarkets = () => (
|
||||||
|
<>
|
||||||
|
<div style={{ height: '50%' }}>
|
||||||
|
<Markets />
|
||||||
|
</div>
|
||||||
|
<div style={{ height: '50%' }}>
|
||||||
|
<Markets />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
export default TwoMarkets;
|
export default TwoMarkets;
|
||||||
|
@ -1,89 +1,82 @@
|
|||||||
import type { GridApi, ValueFormatterParams } from 'ag-grid-community';
|
import { forwardRef } from 'react';
|
||||||
import {
|
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||||
PriceCell,
|
import { PriceCell, formatNumber } from '@vegaprotocol/react-helpers';
|
||||||
formatNumber,
|
|
||||||
useApplyGridTransaction,
|
|
||||||
} from '@vegaprotocol/react-helpers';
|
|
||||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Markets_markets } from '@vegaprotocol/graphql';
|
import { Markets_markets } from '@vegaprotocol/graphql';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
import { useRef, useState } from 'react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
interface MarketListTableProps {
|
interface MarketListTableProps {
|
||||||
markets: Markets_markets[];
|
markets: Markets_markets[];
|
||||||
onRowClicked: (marketId: string) => void;
|
onRowClicked: (marketId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MarketListTable = ({
|
export const MarketListTable = forwardRef<AgGridReact, MarketListTableProps>(
|
||||||
markets,
|
({ markets, onRowClicked }, ref) => {
|
||||||
onRowClicked,
|
const [initialMarkets] = useState(markets);
|
||||||
}: MarketListTableProps) => {
|
const getRowNodeId = (data: Markets_markets) => data.id;
|
||||||
const [initialMarkets] = useState(markets);
|
|
||||||
const gridApi = useRef<GridApi | null>(null);
|
|
||||||
useApplyGridTransaction<Markets_markets>(markets, gridApi.current);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
overlayNoRowsTemplate="No markets"
|
overlayNoRowsTemplate="No markets"
|
||||||
rowData={initialMarkets}
|
rowData={initialMarkets}
|
||||||
getRowNodeId={(data) => data.id}
|
getRowNodeId={getRowNodeId}
|
||||||
suppressCellFocus={true}
|
ref={ref}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
}}
|
}}
|
||||||
onGridReady={(params) => {
|
onRowClicked={({ data }) => onRowClicked(data.id)}
|
||||||
gridApi.current = params.api;
|
components={{ PriceCell }}
|
||||||
}}
|
>
|
||||||
onRowClicked={({ data }) => onRowClicked(data.id)}
|
<AgGridColumn
|
||||||
components={{ PriceCell }}
|
headerName="Market"
|
||||||
>
|
field="tradableInstrument.instrument.code"
|
||||||
<AgGridColumn
|
/>
|
||||||
headerName="Market"
|
<AgGridColumn
|
||||||
field="tradableInstrument.instrument.code"
|
headerName="Settlement asset"
|
||||||
/>
|
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
||||||
<AgGridColumn
|
/>
|
||||||
headerName="Settlement asset"
|
<AgGridColumn
|
||||||
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
headerName="State"
|
||||||
/>
|
field="data"
|
||||||
<AgGridColumn
|
valueFormatter={({ value }: ValueFormatterParams) =>
|
||||||
headerName="State"
|
`${value.market.state} (${value.market.tradingMode})`
|
||||||
field="data"
|
}
|
||||||
valueFormatter={({ value }: ValueFormatterParams) =>
|
/>
|
||||||
`${value.market.state} (${value.market.tradingMode})`
|
<AgGridColumn
|
||||||
}
|
headerName="Best bid"
|
||||||
/>
|
field="data.bestBidPrice"
|
||||||
<AgGridColumn
|
type="rightAligned"
|
||||||
headerName="Best bid"
|
cellRenderer="PriceCell"
|
||||||
field="data.bestBidPrice"
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
type="rightAligned"
|
formatNumber(value, data.decimalPlaces)
|
||||||
cellRenderer="PriceCell"
|
}
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
/>
|
||||||
formatNumber(value, data.decimalPlaces)
|
<AgGridColumn
|
||||||
}
|
headerName="Best offer"
|
||||||
/>
|
field="data.bestOfferPrice"
|
||||||
<AgGridColumn
|
type="rightAligned"
|
||||||
headerName="Best offer"
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
field="data.bestOfferPrice"
|
formatNumber(value, data.decimalPlaces)
|
||||||
type="rightAligned"
|
}
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
cellRenderer="PriceCell"
|
||||||
formatNumber(value, data.decimalPlaces)
|
/>
|
||||||
}
|
<AgGridColumn
|
||||||
cellRenderer="PriceCell"
|
headerName="Mark price"
|
||||||
/>
|
field="data.markPrice"
|
||||||
<AgGridColumn
|
type="rightAligned"
|
||||||
headerName="Mark price"
|
cellRenderer="PriceCell"
|
||||||
field="data.markPrice"
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
type="rightAligned"
|
formatNumber(value, data.decimalPlaces)
|
||||||
cellRenderer="PriceCell"
|
}
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
/>
|
||||||
formatNumber(value, data.decimalPlaces)
|
<AgGridColumn headerName="Description" field="name" />
|
||||||
}
|
</AgGrid>
|
||||||
/>
|
);
|
||||||
<AgGridColumn headerName="Description" field="name" />
|
}
|
||||||
</AgGrid>
|
);
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MarketListTable;
|
export default MarketListTable;
|
||||||
|
@ -1,10 +1,48 @@
|
|||||||
import { GridApi } from 'ag-grid-community';
|
import { GridApi } from 'ag-grid-community';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
|
import { produce } from 'immer';
|
||||||
|
|
||||||
export const useApplyGridTransaction = <T extends { id: string }>(
|
export const updateCallback =
|
||||||
|
<T>(
|
||||||
|
gridApiRef: { current: GridApi | null },
|
||||||
|
getRowNodeId: (row: T) => string
|
||||||
|
) =>
|
||||||
|
(data: T[]) => {
|
||||||
|
if (!gridApiRef.current) return;
|
||||||
|
|
||||||
|
const update: T[] = [];
|
||||||
|
const add: T[] = [];
|
||||||
|
|
||||||
|
// split into updates and adds
|
||||||
|
data.forEach((d) => {
|
||||||
|
if (!gridApiRef.current) return;
|
||||||
|
|
||||||
|
const rowNode = gridApiRef.current.getRowNode(getRowNodeId(d));
|
||||||
|
|
||||||
|
if (rowNode) {
|
||||||
|
if (
|
||||||
|
produce(rowNode.data, (draft: T) => Object.assign(draft, d)) !==
|
||||||
|
rowNode.data
|
||||||
|
) {
|
||||||
|
update.push(d);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add.push(d);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// async transaction for optimal handling of high grequency updates
|
||||||
|
gridApiRef.current.applyTransactionAsync({
|
||||||
|
update,
|
||||||
|
add,
|
||||||
|
addIndex: 0,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useApplyGridTransaction = <T>(
|
||||||
data: T[],
|
data: T[],
|
||||||
gridApi: GridApi | null
|
gridApi: GridApi | null,
|
||||||
|
getRowNodeId: (row: T) => string
|
||||||
) => {
|
) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gridApi) return;
|
if (!gridApi) return;
|
||||||
@ -16,7 +54,7 @@ export const useApplyGridTransaction = <T extends { id: string }>(
|
|||||||
data.forEach((d) => {
|
data.forEach((d) => {
|
||||||
if (!gridApi) return;
|
if (!gridApi) return;
|
||||||
|
|
||||||
const rowNode = gridApi.getRowNode(d.id);
|
const rowNode = gridApi.getRowNode(getRowNodeId(d));
|
||||||
|
|
||||||
if (rowNode) {
|
if (rowNode) {
|
||||||
if (!isEqual(rowNode.data, d)) {
|
if (!isEqual(rowNode.data, d)) {
|
||||||
@ -26,11 +64,11 @@ export const useApplyGridTransaction = <T extends { id: string }>(
|
|||||||
add.push(d);
|
add.push(d);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// async transaction for optimal handling of high grequency updates
|
||||||
gridApi.applyTransaction({
|
gridApi.applyTransaction({
|
||||||
update,
|
update,
|
||||||
add,
|
add,
|
||||||
addIndex: 0,
|
addIndex: 0,
|
||||||
});
|
});
|
||||||
}, [data, gridApi]);
|
}, [data, gridApi, getRowNodeId]);
|
||||||
};
|
};
|
||||||
|
@ -15,14 +15,13 @@ const AgGridDarkTheme = dynamic<{ children: React.ReactElement }>(
|
|||||||
{ ssr: false }
|
{ ssr: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AgGridThemed = ({
|
export const AgGridThemed = React.forwardRef<
|
||||||
style,
|
AgGridReact,
|
||||||
className,
|
(AgGridReactProps | AgReactUiProps) & {
|
||||||
...props
|
style?: React.CSSProperties;
|
||||||
}: (AgGridReactProps | AgReactUiProps) & {
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
}
|
||||||
className?: string;
|
>(({ style, className, ...props }, ref) => {
|
||||||
}) => {
|
|
||||||
const theme = React.useContext(ThemeContext);
|
const theme = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -33,13 +32,13 @@ export const AgGridThemed = ({
|
|||||||
>
|
>
|
||||||
{theme === 'dark' ? (
|
{theme === 'dark' ? (
|
||||||
<AgGridDarkTheme>
|
<AgGridDarkTheme>
|
||||||
<AgGridReact {...props} />
|
<AgGridReact {...props} ref={ref} />
|
||||||
</AgGridDarkTheme>
|
</AgGridDarkTheme>
|
||||||
) : (
|
) : (
|
||||||
<AgGridLightTheme>
|
<AgGridLightTheme>
|
||||||
<AgGridReact {...props} />
|
<AgGridReact {...props} ref={ref} />
|
||||||
</AgGridLightTheme>
|
</AgGridLightTheme>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
|
import * as React from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
|
||||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
import type {
|
||||||
|
AgGridReactProps,
|
||||||
|
AgReactUiProps,
|
||||||
|
AgGridReact,
|
||||||
|
} from 'ag-grid-react';
|
||||||
|
|
||||||
|
type Props = (AgGridReactProps | AgReactUiProps) & {
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
className?: string;
|
||||||
|
ref?: React.Ref<AgGridReact>;
|
||||||
|
};
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/69433673/nextjs-reactdomserver-does-not-yet-support-suspense
|
// https://stackoverflow.com/questions/69433673/nextjs-reactdomserver-does-not-yet-support-suspense
|
||||||
export const AgGridDynamic = dynamic<
|
const AgGridDynamicInternal = dynamic<Props>(
|
||||||
(AgGridReactProps | AgReactUiProps) & {
|
() => import('./ag-grid-dynamic-themed').then((mod) => mod.AgGridThemed),
|
||||||
style?: React.CSSProperties;
|
{
|
||||||
className?: string;
|
ssr: false,
|
||||||
|
// https://nextjs.org/docs/messages/invalid-dynamic-suspense
|
||||||
|
// suspense: true
|
||||||
}
|
}
|
||||||
>(() => import('./ag-grid-dynamic-themed').then((mod) => mod.AgGridThemed), {
|
);
|
||||||
ssr: false,
|
|
||||||
// https://nextjs.org/docs/messages/invalid-dynamic-suspense
|
export const AgGridDynamic = React.forwardRef<AgGridReact>((props, ref) => (
|
||||||
// suspense: true
|
<AgGridDynamicInternal {...props} ref={ref} />
|
||||||
});
|
));
|
||||||
|
@ -16,14 +16,13 @@ const AgGridDarkTheme = React.lazy(() =>
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AgGridThemed = ({
|
export const AgGridThemed = React.forwardRef<
|
||||||
style,
|
AgGridReact,
|
||||||
className,
|
(AgGridReactProps | AgReactUiProps) & {
|
||||||
...props
|
style?: React.CSSProperties;
|
||||||
}: (AgGridReactProps | AgReactUiProps) & {
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
}
|
||||||
className?: string;
|
>(({ style, className, ...props }, ref) => {
|
||||||
}) => {
|
|
||||||
const theme = React.useContext(ThemeContext);
|
const theme = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -34,13 +33,13 @@ export const AgGridThemed = ({
|
|||||||
>
|
>
|
||||||
{theme === 'dark' ? (
|
{theme === 'dark' ? (
|
||||||
<AgGridDarkTheme>
|
<AgGridDarkTheme>
|
||||||
<AgGridReact {...props} />
|
<AgGridReact {...props} ref={ref} />
|
||||||
</AgGridDarkTheme>
|
</AgGridDarkTheme>
|
||||||
) : (
|
) : (
|
||||||
<AgGridLightTheme>
|
<AgGridLightTheme>
|
||||||
<AgGridReact {...props} />
|
<AgGridReact {...props} ref={ref} />
|
||||||
</AgGridLightTheme>
|
</AgGridLightTheme>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
|
||||||
const LazyAgGridStyled = React.lazy(() =>
|
export const AgGridLazyInternal = React.lazy(() =>
|
||||||
import('./ag-grid-lazy-themed').then((module) => ({
|
import('./ag-grid-lazy-themed').then((module) => ({
|
||||||
default: module.AgGridThemed,
|
default: module.AgGridThemed,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AgGridLazy = (
|
export const AgGridLazy = React.forwardRef<AgGridReact>((props, ref) => (
|
||||||
props: (AgGridReactProps | AgReactUiProps) & { style: React.CSSProperties }
|
<AgGridLazyInternal {...props} ref={ref} />
|
||||||
) => <LazyAgGridStyled {...props} />;
|
));
|
||||||
|
Loading…
Reference in New Issue
Block a user