Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
Improve types in Query component. Make data be undefined in initial l…
Browse files Browse the repository at this point in the history
…oad. (#1581)
  • Loading branch information
leoasis authored and James Baxley committed Jan 25, 2018
1 parent 91c1b3f commit 12821cf
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 19 deletions.
30 changes: 18 additions & 12 deletions src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ const shallowEqual = require('fbjs/lib/shallowEqual');
const invariant = require('invariant');
const pick = require('lodash/pick');

function observableQueryFields(observable) {
type ObservableQueryFields<TData> = Pick<ObservableQuery<TData>, 'refetch' | 'fetchMore' | 'updateQuery' | 'startPolling' | 'stopPolling'>;

function observableQueryFields<TData>(observable: ObservableQuery<TData>): ObservableQueryFields<TData> {
const fields = pick(
observable,
'refetch',
Expand All @@ -38,39 +40,43 @@ function observableQueryFields(observable) {
return fields;
}

export interface QueryResult<TData = any> {
function isDataFilled<TData>(data: {} | TData): data is TData {
return Object.keys(data).length > 0;
}

export interface QueryResult<TData = any, TVariables = OperationVariables> {
client: ApolloClient<any>;
data: TData;
data?: TData;
error?: ApolloError;
fetchMore: (
fetchMoreOptions: FetchMoreQueryOptions & FetchMoreOptions,
) => Promise<ApolloQueryResult<any>>;
loading: boolean;
networkStatus: number;
refetch: (variables?: OperationVariables) => Promise<ApolloQueryResult<any>>;
refetch: (variables?: TVariables) => Promise<ApolloQueryResult<any>>;
startPolling: (pollInterval: number) => void;
stopPolling: () => void;
updateQuery: (
mapFn: (previousQueryResult: any, options: UpdateQueryOptions) => any,
) => void;
}

export interface QueryProps<TData = any> {
children: (result: QueryResult<TData>) => React.ReactNode;
export interface QueryProps<TData = any, TVariables = OperationVariables> {
children: (result: QueryResult<TData, TVariables>) => React.ReactNode;
fetchPolicy?: FetchPolicy;
notifyOnNetworkStatusChange?: boolean;
pollInterval?: number;
query: DocumentNode;
variables?: OperationVariables;
variables?: TVariables;
ssr?: boolean;
}

export interface QueryState<TData = any> {
result: ApolloCurrentResult<TData>;
}

class Query<TData = any> extends React.Component<
QueryProps<TData>,
class Query<TData = any, TVariables = OperationVariables> extends React.Component<
QueryProps<TData, TVariables>,
QueryState<TData>
> {
static contextTypes = {
Expand All @@ -82,7 +88,7 @@ class Query<TData = any> extends React.Component<
private queryObservable: ObservableQuery<TData>;
private querySubscription: ZenObservable.Subscription;

constructor(props: QueryProps<TData>, context: any) {
constructor(props: QueryProps<TData, TVariables>, context: any) {
super(props, context);

invariant(
Expand Down Expand Up @@ -217,12 +223,12 @@ class Query<TData = any> extends React.Component<
this.setState({ result: this.queryObservable.currentResult() });
};

private getQueryResult = (): QueryResult<TData> => {
private getQueryResult = (): QueryResult<TData, TVariables> => {
const { result } = this.state;
const { loading, error, networkStatus, data } = result;
return {
client: this.client,
data,
data: isDataFilled(data) ? data : undefined,
loading,
error,
networkStatus,
Expand Down
2 changes: 1 addition & 1 deletion test/client/Query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ describe('Query component', () => {
{result => {
catchAsyncError(done, () => {
expect(result.loading).toBeFalsy();
expect(result.data).toEqual({});
expect(result.data).toBeUndefined();
expect(result.networkStatus).toBe(7);
done();
});
Expand Down
2 changes: 1 addition & 1 deletion test/client/__snapshots__/Query.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Object {

exports[`Query component calls the children prop: result in render prop while loading 1`] = `
Object {
"data": Object {},
"data": undefined,
"error": undefined,
"fetchMore": [Function],
"loading": true,
Expand Down
10 changes: 5 additions & 5 deletions test/server/getDataFromTree.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -939,11 +939,11 @@ describe('SSR', () => {
}
}
`;
const data = { currentUser: { firstName: 'James' } };
const resultData = { currentUser: { firstName: 'James' } };
const variables = { id: 1 };
const link = mockSingleLink({
request: { query, variables },
result: { data },
result: { data: resultData },
delay: 50,
});

Expand All @@ -959,12 +959,12 @@ describe('SSR', () => {
};
}

class CurrentUserQuery extends Query<Data> {}
class CurrentUserQuery extends Query<Data, { id: number }> {}

const Element = (props: { id: number }) => (
<CurrentUserQuery query={query} ssr={false} variables={props}>
{({ data: { currentUser }, loading }) => (
<div>{loading ? 'loading' : currentUser.firstName}</div>
{({ data, loading }) => (
<div>{loading || !data ? 'loading' : data.currentUser.firstName}</div>
)}
</CurrentUserQuery>
);
Expand Down

0 comments on commit 12821cf

Please sign in to comment.