feat: call update with null data from useDataProvider hook on variables change (#2689)

This commit is contained in:
Bartłomiej Głownia 2023-01-24 15:01:51 +01:00 committed by GitHub
parent 31881f8e5a
commit 0cff5895c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 58 deletions

View File

@ -1,3 +1,3 @@
import { Market } from './market';
import { MarketPage } from './market';
export default Market;
export default MarketPage;

View File

@ -5,6 +5,7 @@ import {
t,
titlefy,
useDataProvider,
useThrottledDataProvider,
} from '@vegaprotocol/react-helpers';
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import type {
@ -31,7 +32,47 @@ export interface SingleMarketData extends SingleMarketFieldsFragment {
data: MarketData;
}
export const Market = () => {
const TitleUpdater = ({
marketId,
marketName,
decimalPlaces,
}: {
marketId?: string;
marketName?: string;
decimalPlaces?: number;
}) => {
const pageTitle = usePageTitleStore((store) => store.pageTitle);
const updateTitle = usePageTitleStore((store) => store.updateTitle);
const { data: marketData } = useThrottledDataProvider<
MarketData,
MarketDataUpdateFieldsFragment
>(
{
dataProvider: marketDataProvider,
variables: useMemo(() => ({ marketId }), [marketId]),
skip: !marketId,
},
1000
);
useEffect(() => {
const marketPrice = calculatePrice(marketData?.markPrice, decimalPlaces);
if (marketName) {
const newPageTitle = titlefy([marketName, marketPrice]);
if (pageTitle !== newPageTitle) {
updateTitle(newPageTitle);
}
}
}, [
decimalPlaces,
marketName,
marketData?.markPrice,
pageTitle,
updateTitle,
]);
return null;
};
export const MarketPage = () => {
const { marketId } = useParams();
const navigate = useNavigate();
@ -39,9 +80,6 @@ export const Market = () => {
const update = useGlobalStore((store) => store.update);
const lastMarketId = useGlobalStore((store) => store.marketId);
const pageTitle = usePageTitleStore((store) => store.pageTitle);
const updateTitle = usePageTitleStore((store) => store.updateTitle);
const onSelect = useCallback(
(id: string) => {
if (id && id !== marketId) {
@ -51,56 +89,20 @@ export const Market = () => {
[marketId, navigate]
);
const variables = useMemo(
() => ({
marketId: marketId || '',
}),
[marketId]
);
const updateMarketId = useCallback(
({ data }: { data: { id?: string } | null }) => {
if (data?.id && data.id !== lastMarketId) {
update({ marketId: data.id });
}
return true;
},
[update, lastMarketId]
);
const { data, error, loading } = useDataProvider<
SingleMarketFieldsFragment,
never
>({
dataProvider: marketProvider,
variables,
update: updateMarketId,
variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]),
skip: !marketId,
});
const marketName = data?.tradableInstrument.instrument.name;
const updateProvider = useCallback(
({ data: marketData }: { data: MarketData | null }) => {
const marketPrice = calculatePrice(
marketData?.markPrice,
data?.decimalPlaces
);
if (marketName) {
const newPageTitle = titlefy([marketName, marketPrice]);
if (pageTitle !== newPageTitle) {
updateTitle(newPageTitle);
}
}
return true;
},
[updateTitle, pageTitle, marketName, data?.decimalPlaces]
);
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider,
update: updateProvider,
variables,
skip: !marketId || !data,
});
useEffect(() => {
if (data?.id && data.id !== lastMarketId) {
update({ marketId: data.id });
}
}, [update, lastMarketId, data?.id]);
const tradeView = useMemo(() => {
if (w > 960) {
@ -123,6 +125,11 @@ export const Market = () => {
data={data || undefined}
noDataCondition={(data) => false}
>
<TitleUpdater
marketId={data?.id}
marketName={data?.tradableInstrument.instrument.name}
decimalPlaces={data?.decimalPlaces}
/>
{tradeView}
</AsyncRenderer>
);

View File

@ -17,15 +17,11 @@ export const useAccountBalance = (assetId?: string) => {
const account = assetId
? getSettlementAccount({ accounts: data, assetId })
: undefined;
if (accountBalance !== account?.balance) {
setAccountBalance(account?.balance || '');
}
if (accountDecimals !== account?.asset.decimals) {
setAccountDecimals(account?.asset.decimals || null);
}
setAccountBalance(account?.balance || '');
setAccountDecimals(account?.asset.decimals || null);
return true;
},
[accountBalance, accountDecimals, assetId]
[assetId]
);
useDataProvider({

View File

@ -161,6 +161,13 @@ describe('useDataProvider hook', () => {
});
expect(update).toBeCalledTimes(1);
// setting same variables, with different object reference
await act(async () => {
rerender({ dataProvider, update, variables: { ...variables } });
});
expect(unsubscribe).toBeCalledTimes(0);
expect(dataProvider).toBeCalledTimes(1);
// changing variables after date was loaded
await act(async () => {
rerender({ dataProvider, update, variables: { partyId: '0x321' } });
@ -173,7 +180,7 @@ describe('useDataProvider hook', () => {
await act(async () => {
callback({ ...updateCallbackPayload });
});
expect(update).toBeCalledTimes(2);
expect(update).toBeCalledTimes(3);
// changing variables, apollo query will return error
await act(async () => {
@ -193,7 +200,7 @@ describe('useDataProvider hook', () => {
pageInfo: null,
});
});
expect(update).toBeCalledTimes(3);
expect(update).toBeCalledTimes(5);
});
it('do not create data provider instance when skip is true', async () => {

View File

@ -1,6 +1,8 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import throttle from 'lodash/throttle';
import isEqual from 'lodash/isEqual';
import { useApolloClient } from '@apollo/client';
import { usePrevious } from './use-previous';
import type { OperationVariables } from '@apollo/client';
import type {
Subscribe,
@ -52,9 +54,9 @@ export const useDataProvider = <
dataProvider,
update,
insert,
variables,
skipUpdates,
skip,
...props
}: useDataProviderParams<Data, Delta, Variables>) => {
const client = useApolloClient();
const [data, setData] = useState<Data | null>(null);
@ -65,6 +67,13 @@ export const useDataProvider = <
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
const loadRef = useRef<Load<Data> | undefined>(undefined);
const initialized = useRef<boolean>(false);
const prevVariables = usePrevious(props.variables);
const [variables, setVariables] = useState(props.variables);
useEffect(() => {
if (!isEqual(prevVariables, props.variables)) {
setVariables(props.variables);
}
}, [props.variables, prevVariables]);
const flush = useCallback(() => {
if (flushRef.current) {
flushRef.current();
@ -125,6 +134,9 @@ export const useDataProvider = <
setData(null);
setError(undefined);
setTotalCount(undefined);
if (initialized.current && update) {
update({ data: null });
}
initialized.current = false;
if (skip) {
setLoading(false);