vega-frontend-monorepo/libs/react-helpers/src/hooks/use-data-provider.ts
Bartłomiej Głownia a08f63c7d8
Feature/1243 market data providers refactoring (#1254)
* feat(#1243): Market data providers

* feat(#1243): Market data providers

* feat(#1243): Market data providers

* feat(#1243): refactor market lists

* feat(#1243): refactor market lists

* feat(#1243): refactor market lists

* feat(#1243): refactor orderbook data providers

* feat(#1243): refactor orderbook data providers

* feat(#1243): refactor depth chart data layer

* feat(#1243): fix market depth typing

* fixed unit tests

* feat(#1243): e2e test fixes

* feat(#1243): code style fixes

* feat(#1243): post merge fixes

* feat(#1243): fix lint issues

* feat(#1243): post merge fixes

* feat(#1243): remove market name from market

* feat(#1243): fix console lite e2e data depth mocks

* feat(#1243): fix console lite e2e market trade test

* feat(#1243): fix lint issues

* feat(#1243): fix trading e2e home test

Co-authored-by: asiaznik <artur@vegaprotocol.io>
2022-09-13 12:14:06 +02:00

121 lines
3.5 KiB
TypeScript

import { useState, useEffect, useRef, useCallback } from 'react';
import { useApolloClient } from '@apollo/client';
import type { OperationVariables } from '@apollo/client';
import type {
Subscribe,
Load,
UpdateCallback,
} from '../lib/generic-data-provider';
/**
*
* @param dataProvider subscribe function created by makeDataProvider
* @param update optional function called on each delta received in subscription, if returns true updated data will be not passed from hook (component handles updates internally)
* @param variables optional
* @returns state: data, loading, error, methods: flush (pass updated data to update function without delta), restart: () => void}};
*/
export function useDataProvider<Data, Delta>({
dataProvider,
update,
insert,
variables,
noUpdate,
skip,
}: {
dataProvider: Subscribe<Data, Delta>;
update?: ({ delta, data }: { delta: Delta; data: Data }) => boolean;
insert?: ({
insertionData,
data,
totalCount,
}: {
insertionData: Data;
data: Data;
totalCount?: number;
}) => boolean;
variables?: OperationVariables;
noUpdate?: boolean;
skip?: boolean;
}) {
const client = useApolloClient();
const [data, setData] = useState<Data | null>(null);
const [totalCount, setTotalCount] = useState<number>();
const [loading, setLoading] = useState<boolean>(!skip);
const [error, setError] = useState<Error | undefined>(undefined);
const flushRef = useRef<(() => void) | undefined>(undefined);
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
const loadRef = useRef<Load<Data> | undefined>(undefined);
const initialized = useRef<boolean>(false);
const flush = useCallback(() => {
if (flushRef.current) {
flushRef.current();
}
}, []);
const reload = useCallback((force = false) => {
if (reloadRef.current) {
reloadRef.current(force);
}
}, []);
const load = useCallback<Load<Data>>((...args) => {
if (loadRef.current) {
return loadRef.current(...args);
}
return Promise.reject();
}, []);
const callback = useCallback<UpdateCallback<Data, Delta>>(
({
data,
error,
loading,
delta,
insertionData,
totalCount,
isInsert,
isUpdate,
}) => {
setError(error);
setLoading(loading);
if (!error && !loading) {
// if update or insert function returns true it means that component handles updates
// component can use flush() which will call callback without delta and cause data state update
if (initialized.current && data) {
if (
isUpdate &&
!noUpdate &&
update &&
(!delta || update({ delta, data }))
) {
return;
}
if (
isInsert &&
insert &&
(!insertionData || insert({ insertionData, data, totalCount }))
) {
return;
}
}
initialized.current = true;
setTotalCount(totalCount);
setData(data);
}
},
[update, insert, noUpdate]
);
useEffect(() => {
if (skip) {
return;
}
const { unsubscribe, flush, reload, load } = dataProvider(
callback,
client,
variables
);
flushRef.current = flush;
reloadRef.current = reload;
loadRef.current = load;
return unsubscribe;
}, [client, initialized, dataProvider, callback, variables, skip]);
return { data, loading, error, flush, reload, load, totalCount };
}