mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-07-01 07:40:10 +00:00
[react-relay] add hook types (#39414)
* add relay-experimental types * add tests to relay-experimental types * update version on header
This commit is contained in:
committed by
Eloy Durán
parent
dc156f32b2
commit
371a2eaabd
1
types/react-relay/hooks.d.ts
vendored
Normal file
1
types/react-relay/hooks.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from './lib/hooks';
|
||||
19
types/react-relay/index.d.ts
vendored
19
types/react-relay/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
// Type definitions for react-relay 6.0
|
||||
// Type definitions for react-relay 7.0
|
||||
// Project: https://github.com/facebook/relay, https://facebook.github.io/relay
|
||||
// Definitions by: Johannes Schickling <https://github.com/graphcool>
|
||||
// Matt Martin <https://github.com/voxmatt>
|
||||
@@ -8,8 +8,9 @@
|
||||
// Kaare Hoff Skovgaard <https://github.com/kastermester>
|
||||
// Matt Krick <https://github.com/mattkrick>
|
||||
// Jared Kass <https://github.com/jdk243>
|
||||
// Renan Machado <https://github.com/renanmav>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 3.0
|
||||
// TypeScript Version: 3.3
|
||||
|
||||
import * as React from 'react';
|
||||
import {
|
||||
@@ -117,13 +118,17 @@ interface QueryRendererProps<TOperation extends OperationType> {
|
||||
}) => React.ReactNode;
|
||||
variables: TOperation['variables'];
|
||||
}
|
||||
declare class ReactRelayQueryRenderer<TOperation extends OperationType> extends React.Component<{
|
||||
cacheConfig?: CacheConfig | null;
|
||||
fetchPolicy?: FetchPolicy;
|
||||
} & QueryRendererProps<TOperation>> {}
|
||||
declare class ReactRelayQueryRenderer<TOperation extends OperationType> extends React.Component<
|
||||
{
|
||||
cacheConfig?: CacheConfig | null;
|
||||
fetchPolicy?: FetchPolicy;
|
||||
} & QueryRendererProps<TOperation>
|
||||
> {}
|
||||
export { ReactRelayQueryRenderer as QueryRenderer };
|
||||
|
||||
declare class ReactRelayLocalQueryRenderer<TOperation extends OperationType> extends React.Component<QueryRendererProps<TOperation>> {}
|
||||
declare class ReactRelayLocalQueryRenderer<TOperation extends OperationType> extends React.Component<
|
||||
QueryRendererProps<TOperation>
|
||||
> {}
|
||||
export { ReactRelayLocalQueryRenderer as LocalQueryRenderer };
|
||||
|
||||
export const ReactRelayContext: React.Context<RelayContext | null>;
|
||||
|
||||
17
types/react-relay/lib/hooks.d.ts
vendored
Normal file
17
types/react-relay/lib/hooks.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export { graphql } from 'relay-runtime';
|
||||
export { fetchQuery } from './relay-experimental/fetchQuery';
|
||||
|
||||
export { EntryPointContainer } from './relay-experimental/EntryPointContainer';
|
||||
export { LazyLoadEntryPointContainer } from './relay-experimental/LazyLoadEntryPointContainer';
|
||||
export { RelayEnvironmentProvider } from './relay-experimental/RelayEnvironmentProvider';
|
||||
|
||||
export { preloadQuery } from './relay-experimental/preloadQuery';
|
||||
export { prepareEntryPoint } from './relay-experimental/prepareEntryPoint';
|
||||
|
||||
export { useBlockingPaginationFragment } from './relay-experimental/useBlockingPaginationFragment';
|
||||
export { useFragment } from './relay-experimental/useFragment';
|
||||
export { useLazyLoadQuery } from './relay-experimental/useLazyLoadQuery';
|
||||
export { useLegacyPaginationFragment as usePaginationFragment } from './relay-experimental/useLegacyPaginationFragment';
|
||||
export { usePreloadedQuery } from './relay-experimental/usePreloadedQuery';
|
||||
export { useRefetchableFragment } from './relay-experimental/useRefetchableFragment';
|
||||
export { useRelayEnvironment } from './relay-experimental/useRelayEnvironment';
|
||||
24
types/react-relay/lib/relay-experimental/EntryPointContainer.d.ts
vendored
Normal file
24
types/react-relay/lib/relay-experimental/EntryPointContainer.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/* tslint:disable:no-unnecessary-generics */
|
||||
|
||||
import { ElementType, ClassicElement } from 'react';
|
||||
|
||||
import { EntryPointComponent, PreloadedEntryPoint } from './EntryPointTypes';
|
||||
|
||||
export function EntryPointContainer<
|
||||
TPreloadedQueries extends {},
|
||||
TPreloadedNestedEntryPoints extends {},
|
||||
TRuntimeProps extends {},
|
||||
TExtraProps,
|
||||
TEntryPointComponent extends EntryPointComponent<
|
||||
TPreloadedQueries,
|
||||
TPreloadedNestedEntryPoints,
|
||||
TRuntimeProps,
|
||||
TExtraProps
|
||||
>
|
||||
>({
|
||||
entryPointReference,
|
||||
props,
|
||||
}: Readonly<{
|
||||
entryPointReference: PreloadedEntryPoint<TEntryPointComponent>;
|
||||
props: TRuntimeProps;
|
||||
}>): ClassicElement<ElementType>;
|
||||
152
types/react-relay/lib/relay-experimental/EntryPointTypes.d.ts
vendored
Normal file
152
types/react-relay/lib/relay-experimental/EntryPointTypes.d.ts
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import {
|
||||
OperationType,
|
||||
ConcreteRequest,
|
||||
RequestParameters,
|
||||
IEnvironment,
|
||||
Observable,
|
||||
GraphQLResponse,
|
||||
} from 'relay-runtime';
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
export type PreloadFetchPolicy = 'store-or-network' | 'store-and-network' | 'network-only';
|
||||
|
||||
export interface PreloadOptions {
|
||||
readonly fetchKey?: string | number;
|
||||
readonly fetchPolicy?: PreloadFetchPolicy;
|
||||
}
|
||||
|
||||
// Note: the phantom type parameter here helps ensures that the
|
||||
// $Parameters.js value matches the type param provided to preloadQuery.
|
||||
// tslint:disable-next-line interface-over-type-literal
|
||||
export type PreloadableConcreteRequest<TQuery extends OperationType> = {};
|
||||
|
||||
export interface EnvironmentProviderOptions {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface PreloadedQuery<
|
||||
TQuery extends OperationType,
|
||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
||||
> {
|
||||
readonly environment: IEnvironment;
|
||||
readonly environmentProviderOptions: TEnvironmentProviderOptions | null | undefined;
|
||||
readonly fetchKey: string | number | null | undefined;
|
||||
readonly fetchPolicy: PreloadFetchPolicy;
|
||||
readonly name: string;
|
||||
readonly source: Observable<GraphQLResponse> | null | undefined;
|
||||
readonly variables: TQuery['variables'];
|
||||
}
|
||||
|
||||
/**
|
||||
* The Interface of the EntryPoints .entrypoint files
|
||||
*
|
||||
* Every .entrypoint file it's an object that must have two required fields:
|
||||
* - getPreloadProps(...) function that will return the description of preloaded
|
||||
* queries and preloaded (nested) entry points for the current entry point
|
||||
* - root - JSResource of the module that will render those preloaded queries
|
||||
*
|
||||
* TEntryPointParams - object that contains all necessary information to execute
|
||||
* the preloaders (routeParams, query variables)
|
||||
*
|
||||
* TPreloadedQueries - queries, defined in the root components
|
||||
*
|
||||
* TPreloadedEntryPoints - nested entry points, defined in the root components
|
||||
*
|
||||
* TRuntimeProps - the type of additional props that you may pass to the
|
||||
* component (like `onClick` handler, etc) during runtime. Values for them
|
||||
* defined during component runtime
|
||||
*
|
||||
* TExtraProps - a bag of extra props that you may define in `entrypoint` file
|
||||
* and they will be passed to the EntryPointComponent as `extraProps`
|
||||
*/
|
||||
export type InternalEntryPointRepresentation<
|
||||
TEntryPointParams,
|
||||
TPreloadedQueries,
|
||||
TPreloadedEntryPoints,
|
||||
TRuntimeProps,
|
||||
TExtraProps
|
||||
> = Readonly<{
|
||||
getPreloadProps: (
|
||||
entryPointParams: TEntryPointParams,
|
||||
) => PreloadProps<TEntryPointParams, TPreloadedQueries, TPreloadedEntryPoints, TExtraProps>;
|
||||
root: unknown;
|
||||
}>;
|
||||
|
||||
// The shape of the props of the entry point `root` component
|
||||
export type EntryPointProps<
|
||||
TPreloadedQueries,
|
||||
TPreloadedEntryPoints = {},
|
||||
TRuntimeProps = {},
|
||||
TExtraProps = null
|
||||
> = Readonly<{
|
||||
entryPoints: TPreloadedEntryPoints;
|
||||
extraProps: TExtraProps | null;
|
||||
props: TRuntimeProps;
|
||||
queries: TPreloadedQueries;
|
||||
}>;
|
||||
|
||||
// Type of the entry point `root` component
|
||||
export type EntryPointComponent<
|
||||
TPreloadedQueries,
|
||||
TPreloadedEntryPoints = {},
|
||||
TRuntimeProps = {},
|
||||
TExtraProps = null
|
||||
> = Component<EntryPointProps<TPreloadedQueries, TPreloadedEntryPoints, TRuntimeProps, TExtraProps>>;
|
||||
|
||||
// Return type of the `getPreloadProps(...)` of the entry point
|
||||
export type PreloadProps<
|
||||
TPreloadParams,
|
||||
TPreloadedQueries extends {},
|
||||
TPreloadedEntryPoints extends {},
|
||||
TExtraProps = null,
|
||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
||||
> = Readonly<{
|
||||
entryPoints?: { [T in keyof TPreloadedEntryPoints]: ExtractEntryPointTypeHelper<TPreloadParams> };
|
||||
extraProps?: TExtraProps;
|
||||
queries?: { [T in keyof TPreloadedQueries]: ExtractQueryTypeHelper<TEnvironmentProviderOptions> };
|
||||
}>;
|
||||
|
||||
// Return type of the `prepareEntryPoint(...)` function
|
||||
export type PreloadedEntryPoint<TEntryPointComponent> = Readonly<{
|
||||
entryPoints: JSX.LibraryManagedAttributes<TEntryPointComponent, 'entryPoints'>;
|
||||
extraProps: JSX.LibraryManagedAttributes<TEntryPointComponent, 'extraProps'>;
|
||||
getComponent: () => TEntryPointComponent;
|
||||
queries: JSX.LibraryManagedAttributes<TEntryPointComponent, 'queries'>;
|
||||
}>;
|
||||
|
||||
export type ThinQueryParams<TQuery extends OperationType, TEnvironmentProviderOptions> = Readonly<{
|
||||
environmentProviderOptions?: TEnvironmentProviderOptions | null;
|
||||
options?: PreloadOptions | null;
|
||||
parameters: PreloadableConcreteRequest<TQuery>;
|
||||
variables: TQuery['variables'];
|
||||
}>;
|
||||
|
||||
export type ThinNestedEntryPointParams<TEntryPointParams, TEntryPoint> = Readonly<{
|
||||
entryPoint: TEntryPoint;
|
||||
entryPointParams: TEntryPointParams;
|
||||
}>;
|
||||
|
||||
export type ExtractQueryTypeHelper<TEnvironmentProviderOptions> = <TQuery extends OperationType>(
|
||||
query: PreloadedQuery<TQuery>,
|
||||
) => ThinQueryParams<TQuery, TEnvironmentProviderOptions>;
|
||||
|
||||
export type ExtractEntryPointTypeHelper<TEntryPointParams> = <TEntryPointComponent>(
|
||||
entryPoint: PreloadedEntryPoint<TEntryPointComponent> | null | undefined,
|
||||
) =>
|
||||
| ThinNestedEntryPointParams<TEntryPointParams, EntryPoint<TEntryPointParams, TEntryPointComponent>>
|
||||
| null
|
||||
| undefined;
|
||||
|
||||
export type EntryPoint<TEntryPointParams, TEntryPointComponent> = InternalEntryPointRepresentation<
|
||||
TEntryPointParams,
|
||||
JSX.LibraryManagedAttributes<TEntryPointComponent, 'queries'>,
|
||||
JSX.LibraryManagedAttributes<TEntryPointComponent, 'entryPoints'>,
|
||||
JSX.LibraryManagedAttributes<TEntryPointComponent, 'props'>,
|
||||
JSX.LibraryManagedAttributes<TEntryPointComponent, 'extraProps'>
|
||||
>;
|
||||
|
||||
// tslint:disable-next-line interface-name
|
||||
export interface IEnvironmentProvider<TOptions> {
|
||||
getEnvironment(options: TOptions | null): IEnvironment;
|
||||
}
|
||||
46
types/react-relay/lib/relay-experimental/LRUCache.d.ts
vendored
Normal file
46
types/react-relay/lib/relay-experimental/LRUCache.d.ts
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
export interface Cache<T> {
|
||||
get(key: string): T | null;
|
||||
set(key: string, value: T): void;
|
||||
has(key: string): boolean;
|
||||
delete(key: string): void;
|
||||
size(): number;
|
||||
capacity(): number;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* JS maps (both plain objects and Map) maintain key insertion
|
||||
* order, which means there is an easy way to simulate LRU behavior
|
||||
* that should also perform quite well:
|
||||
*
|
||||
* To insert a new value, first delete the key from the inner _map,
|
||||
* then _map.set(k, v). By deleting and reinserting, you ensure that the
|
||||
* map sees the key as the last inserted key.
|
||||
*
|
||||
* Get does the same: if the key is present, delete and reinsert it.
|
||||
*/
|
||||
declare class LRUCache<T> implements Cache<T> {
|
||||
_capacity: number;
|
||||
_map: Map<string, T>;
|
||||
|
||||
constructor(capacity: number);
|
||||
|
||||
set(key: string, value: T): void;
|
||||
|
||||
get(key: string): T | null;
|
||||
|
||||
has(key: string): boolean;
|
||||
|
||||
delete(key: string): void;
|
||||
|
||||
size(): number;
|
||||
|
||||
capacity(): number;
|
||||
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-unnecessary-generics
|
||||
declare function create<T>(capacity: number): LRUCache<T>;
|
||||
|
||||
export { create };
|
||||
43
types/react-relay/lib/relay-experimental/LazyLoadEntryPointContainer.d.ts
vendored
Normal file
43
types/react-relay/lib/relay-experimental/LazyLoadEntryPointContainer.d.ts
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { EntryPoint, EntryPointComponent, EnvironmentProviderOptions, IEnvironmentProvider } from './EntryPointTypes';
|
||||
|
||||
export type EntryPointContainerProps<
|
||||
TEntryPointParams,
|
||||
TPreloadedQueries,
|
||||
TPreloadedEntryPoints,
|
||||
TRuntimeProps,
|
||||
TExtraProps
|
||||
> = Readonly<
|
||||
Readonly<{
|
||||
entryPoint: EntryPoint<
|
||||
TEntryPointParams,
|
||||
EntryPointComponent<TPreloadedQueries, TPreloadedEntryPoints, TRuntimeProps, TExtraProps>
|
||||
>;
|
||||
entryPointParams: TEntryPointParams;
|
||||
environmentProvider?: IEnvironmentProvider<EnvironmentProviderOptions>;
|
||||
props: TRuntimeProps;
|
||||
}>
|
||||
>;
|
||||
|
||||
export function LazyLoadEntryPointContainer<
|
||||
TEntryPointParams extends {},
|
||||
TPreloadedQueries extends {},
|
||||
TPreloadedEntryPoints extends {},
|
||||
TRuntimeProps extends {},
|
||||
TExtraProps
|
||||
>({
|
||||
entryPoint,
|
||||
entryPointParams,
|
||||
props,
|
||||
environmentProvider,
|
||||
}: EntryPointContainerProps<
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TEntryPointParams,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TPreloadedQueries,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TPreloadedEntryPoints,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TRuntimeProps,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TExtraProps
|
||||
>): JSX.Element;
|
||||
84
types/react-relay/lib/relay-experimental/QueryResource.d.ts
vendored
Normal file
84
types/react-relay/lib/relay-experimental/QueryResource.d.ts
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
import {
|
||||
Disposable,
|
||||
FragmentPointer,
|
||||
GraphQLResponse,
|
||||
IEnvironment,
|
||||
Observable,
|
||||
Observer,
|
||||
OperationDescriptor,
|
||||
ReaderFragment,
|
||||
Snapshot,
|
||||
} from 'relay-runtime';
|
||||
import { Cache } from './LRUCache';
|
||||
|
||||
export type QueryResource = QueryResourceImpl;
|
||||
export type FetchPolicy = 'store-only' | 'store-or-network' | 'store-and-network' | 'network-only';
|
||||
export type RenderPolicy = 'full' | 'partial';
|
||||
|
||||
type QueryResourceCache = Cache<QueryResourceCacheEntry>;
|
||||
interface QueryResourceCacheEntry {
|
||||
readonly cacheKey: string;
|
||||
getRetainCount(): number;
|
||||
getValue(): Error | Promise<void> | QueryResult;
|
||||
setValue(value: Error | Promise<void> | QueryResult): void;
|
||||
temporaryRetain(environment: IEnvironment): void;
|
||||
permanentRetain(environment: IEnvironment): Disposable;
|
||||
}
|
||||
interface QueryResult {
|
||||
cacheKey: string;
|
||||
fragmentNode: ReaderFragment;
|
||||
fragmentRef: FragmentPointer;
|
||||
operation: OperationDescriptor;
|
||||
}
|
||||
|
||||
declare function getQueryCacheKey(
|
||||
operation: OperationDescriptor,
|
||||
fetchPolicy: FetchPolicy,
|
||||
renderPolicy: RenderPolicy,
|
||||
): string;
|
||||
|
||||
declare function getQueryResult(operation: OperationDescriptor, cacheKey: string): QueryResult;
|
||||
|
||||
declare function createQueryResourceCacheEntry(
|
||||
cacheKey: string,
|
||||
operation: OperationDescriptor,
|
||||
value: Error | Promise<void> | QueryResult,
|
||||
onDispose: (entry: QueryResourceCacheEntry) => void,
|
||||
): QueryResourceCacheEntry;
|
||||
|
||||
declare class QueryResourceImpl {
|
||||
constructor(environment: IEnvironment);
|
||||
|
||||
/**
|
||||
* This function should be called during a Component's render function,
|
||||
* to either read an existing cached value for the query, or fetch the query
|
||||
* and suspend.
|
||||
*/
|
||||
prepare(
|
||||
operation: OperationDescriptor,
|
||||
fetchObservable: Observable<GraphQLResponse>,
|
||||
maybeFetchPolicy: FetchPolicy | null,
|
||||
maybeRenderPolicy: RenderPolicy | null,
|
||||
observer?: Observer<Snapshot>,
|
||||
cacheKeyBuster?: string | number,
|
||||
): QueryResult;
|
||||
|
||||
/**
|
||||
* This function should be called during a Component's commit phase
|
||||
* (e.g. inside useEffect), in order to retain the operation in the Relay store
|
||||
* and transfer ownership of the operation to the component lifecycle.
|
||||
*/
|
||||
retain(queryResult: QueryResult): Disposable;
|
||||
|
||||
getCacheEntry(
|
||||
operation: OperationDescriptor,
|
||||
fetchPolicy: FetchPolicy,
|
||||
maybeRenderPolicy?: RenderPolicy,
|
||||
): QueryResourceCacheEntry | null;
|
||||
}
|
||||
|
||||
declare function createQueryResource(environment: IEnvironment): QueryResource;
|
||||
|
||||
declare function getQueryResourceForEnvironment(environment: IEnvironment): QueryResourceImpl;
|
||||
|
||||
export { createQueryResource, getQueryResourceForEnvironment };
|
||||
9
types/react-relay/lib/relay-experimental/RelayEnvironmentProvider.d.ts
vendored
Normal file
9
types/react-relay/lib/relay-experimental/RelayEnvironmentProvider.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { IEnvironment } from 'relay-runtime';
|
||||
|
||||
export interface Props {
|
||||
children: ReactNode;
|
||||
environment: IEnvironment;
|
||||
}
|
||||
|
||||
export function RelayEnvironmentProvider(props: Props): JSX.Element;
|
||||
85
types/react-relay/lib/relay-experimental/fetchQuery.d.ts
vendored
Normal file
85
types/react-relay/lib/relay-experimental/fetchQuery.d.ts
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import { CacheConfig, GraphQLTaggedNode, IEnvironment, Observable, OperationType } from 'relay-runtime';
|
||||
|
||||
/**
|
||||
* Fetches the given query and variables on the provided environment,
|
||||
* and de-dupes identical in-flight requests.
|
||||
*
|
||||
* Observing a request:
|
||||
* ====================
|
||||
* fetchQuery returns an Observable which you can call .subscribe()
|
||||
* on. Subscribe optionally takes an Observer, which you can provide to
|
||||
* observe network events:
|
||||
*
|
||||
* ```
|
||||
* fetchQuery(environment, query, variables).subscribe({
|
||||
* // Called when network requests starts
|
||||
* start: (subsctiption) => {},
|
||||
*
|
||||
* // Called after a payload is received and written to the local store
|
||||
* next: (payload) => {},
|
||||
*
|
||||
* // Called when network requests errors
|
||||
* error: (error) => {},
|
||||
*
|
||||
* // Called when network requests fully completes
|
||||
* complete: () => {},
|
||||
*
|
||||
* // Called when network request is unsubscribed
|
||||
* unsubscribe: (subscription) => {},
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Request Promise:
|
||||
* ================
|
||||
* The obervable can be converted to a Promise with .toPromise(), which will
|
||||
* resolve to a snapshot of the query data when the first response is received
|
||||
* from the server.
|
||||
*
|
||||
* ```
|
||||
* fetchQuery(environment, query, variables).then((data) => {
|
||||
* // ...
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* In-flight request de-duping:
|
||||
* ============================
|
||||
* By default, calling fetchQuery multiple times with the same
|
||||
* environment, query and variables will not initiate a new request if a request
|
||||
* for those same parameters is already in flight.
|
||||
*
|
||||
* A request is marked in-flight from the moment it starts until the moment it
|
||||
* fully completes, regardless of error or successful completion.
|
||||
*
|
||||
* NOTE: If the request completes _synchronously_, calling fetchQuery
|
||||
* a second time with the same arguments in the same tick will _NOT_ de-dupe
|
||||
* the request given that it will no longer be in-flight.
|
||||
*
|
||||
*
|
||||
* Data Retention:
|
||||
* ===============
|
||||
* This function will NOT retain query data, meaning that it is not guaranteed
|
||||
* that the fetched data will remain in the Relay store after the request has
|
||||
* completed.
|
||||
* If you need to retain the query data outside of the network request,
|
||||
* you need to use `environment.retain()`.
|
||||
*
|
||||
*
|
||||
* Cancelling requests:
|
||||
* ====================
|
||||
* If the disposable returned by subscribe is called while the
|
||||
* request is in-flight, the request will be cancelled.
|
||||
*
|
||||
* ```
|
||||
* const disposable = fetchQuery(...).subscribe(...);
|
||||
*
|
||||
* // This will cancel the request if it is in-flight.
|
||||
* disposable.dispose();
|
||||
* ```
|
||||
* NOTE: When using .toPromise(), the request cannot be cancelled.
|
||||
*/
|
||||
export function fetchQuery<TQuery extends OperationType>(
|
||||
environment: IEnvironment,
|
||||
query: GraphQLTaggedNode,
|
||||
variables: TQuery['variables'],
|
||||
options?: { networkCacheConfig?: CacheConfig },
|
||||
): Observable<TQuery['response']>;
|
||||
10
types/react-relay/lib/relay-experimental/preloadQuery.d.ts
vendored
Normal file
10
types/react-relay/lib/relay-experimental/preloadQuery.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import { GraphQLResponse, IEnvironment, OperationType, Subscription } from 'relay-runtime';
|
||||
import { PreloadableConcreteRequest, PreloadedQuery, PreloadFetchPolicy, PreloadOptions } from './EntryPointTypes';
|
||||
|
||||
export function preloadQuery<TQuery extends OperationType, TEnvironmentProviderOptions = any>(
|
||||
environment: IEnvironment,
|
||||
preloadableRequest: PreloadableConcreteRequest<TQuery>,
|
||||
variables: TQuery['variables'],
|
||||
options?: PreloadOptions | null,
|
||||
environmentProviderOptions?: TEnvironmentProviderOptions | null,
|
||||
): PreloadedQuery<TQuery, TEnvironmentProviderOptions>;
|
||||
32
types/react-relay/lib/relay-experimental/prepareEntryPoint.d.ts
vendored
Normal file
32
types/react-relay/lib/relay-experimental/prepareEntryPoint.d.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
EntryPoint,
|
||||
EntryPointComponent,
|
||||
EnvironmentProviderOptions,
|
||||
IEnvironmentProvider,
|
||||
PreloadedEntryPoint,
|
||||
} from './EntryPointTypes';
|
||||
|
||||
export function prepareEntryPoint<
|
||||
TEntryPointParams extends {},
|
||||
TPreloadedQueries extends {},
|
||||
TPreloadedEntryPoints extends {},
|
||||
TRuntimeProps extends {},
|
||||
TExtraProps,
|
||||
TEntryPointComponent extends EntryPointComponent<
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TPreloadedQueries,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TPreloadedEntryPoints,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TRuntimeProps,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TExtraProps
|
||||
>,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
TEntryPoint extends EntryPoint<TEntryPointParams, TEntryPointComponent>
|
||||
>(
|
||||
environmentProvider: IEnvironmentProvider<EnvironmentProviderOptions>,
|
||||
// tslint:disable-next-line no-unnecessary-generics
|
||||
entryPoint: TEntryPoint,
|
||||
entryPointParams: TEntryPointParams,
|
||||
): PreloadedEntryPoint<TEntryPointComponent>;
|
||||
36
types/react-relay/lib/relay-experimental/useBlockingPaginationFragment.d.ts
vendored
Normal file
36
types/react-relay/lib/relay-experimental/useBlockingPaginationFragment.d.ts
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { GraphQLResponse, GraphQLTaggedNode, Observer, OperationType } from 'relay-runtime';
|
||||
|
||||
import { LoadMoreFn, UseLoadMoreFunctionArgs } from './useLoadMoreFunction';
|
||||
import { RefetchFnDynamic } from './useRefetchableFragmentNode';
|
||||
|
||||
export interface ReturnType<TQuery extends OperationType, TKey, TFragmentData> {
|
||||
data: TFragmentData;
|
||||
loadNext: LoadMoreFn;
|
||||
loadPrevious: LoadMoreFn;
|
||||
hasNext: boolean;
|
||||
hasPrevious: boolean;
|
||||
refetch: RefetchFnDynamic<TQuery, TKey>;
|
||||
}
|
||||
|
||||
export type $Call<Fn extends (...args: any[]) => any> = Fn extends (arg: any) => infer RT ? RT : never;
|
||||
|
||||
export type NonNullableReturnType<T extends { readonly ' $data'?: unknown }> = (arg: T) => NonNullable<T[' $data']>;
|
||||
export type NullableReturnType<T extends { readonly ' $data'?: unknown | null }> = (arg: T) => T[' $data'] | null;
|
||||
|
||||
export function useBlockingPaginationFragment<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly ' $data'?: unknown | null }
|
||||
>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
parentFragmentRef: TKey,
|
||||
componentDisplayName?: string,
|
||||
): ReturnType<
|
||||
// tslint:disable-next-line:no-unnecessary-generics
|
||||
TQuery,
|
||||
TKey,
|
||||
// NOTE: This $Call ensures that the type of the returned data is either:
|
||||
// - nullable if the provided ref type is nullable
|
||||
// - non-nullable if the provided ref type is non-nullable
|
||||
// prettier-ignore
|
||||
$Call<NonNullableReturnType<TKey> & NullableReturnType<TKey>>
|
||||
>;
|
||||
41
types/react-relay/lib/relay-experimental/useFragment.d.ts
vendored
Normal file
41
types/react-relay/lib/relay-experimental/useFragment.d.ts
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import { GraphQLTaggedNode } from 'relay-runtime';
|
||||
|
||||
// NOTE: These declares ensure that the type of the returned data is:
|
||||
// - non-nullable if the provided ref type is non-nullable
|
||||
// - nullable if the provided ref type is nullable
|
||||
// - array of non-nullable if the privoided ref type is an array of
|
||||
// non-nullable refs
|
||||
// - array of nullable if the privoided ref type is an array of nullable refs
|
||||
|
||||
type $Call<Fn extends (...args: any[]) => any> = Fn extends (arg: any) => infer RT ? RT : never;
|
||||
|
||||
type NonNullableReturnType<T extends { readonly ' $data'?: unknown }> = (arg: T) => NonNullable<T[' $data']>;
|
||||
type NullableReturnType<T extends { readonly ' $data'?: unknown | null }> = (arg: T) => T[' $data'] | null;
|
||||
type NonNullableArrayReturnType<T extends ReadonlyArray<{ readonly ' $data'?: unknown }>> = (arg: {
|
||||
readonly ' $data': T;
|
||||
}) => Array<NonNullable<T[0][' $data']>>;
|
||||
type NullableArrayReturnType<T extends ReadonlyArray<{ readonly ' $data'?: unknown | null }>> = (
|
||||
arg: T,
|
||||
) => Array<T[0][' $data']> | null;
|
||||
|
||||
export function useFragment<TKey extends { readonly ' $data'?: unknown }>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
fragmentRef: TKey,
|
||||
): $Call<NonNullableReturnType<TKey>>;
|
||||
|
||||
export function useFragment<TKey extends { readonly ' $data'?: unknown | null }>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
fragmentRef: TKey,
|
||||
): $Call<NullableReturnType<TKey>>;
|
||||
|
||||
export function useFragment<TKey extends ReadonlyArray<{ readonly ' $data'?: unknown }>>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
fragmentRef: TKey,
|
||||
): $Call<NonNullableArrayReturnType<TKey>>;
|
||||
|
||||
export function useFragment<TKey extends ReadonlyArray<{ readonly ' $data'?: unknown | null }>>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
fragmentRef: TKey,
|
||||
): $Call<NullableArrayReturnType<TKey>>;
|
||||
|
||||
export {};
|
||||
13
types/react-relay/lib/relay-experimental/useLazyLoadQuery.d.ts
vendored
Normal file
13
types/react-relay/lib/relay-experimental/useLazyLoadQuery.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { FetchPolicy, RenderPolicy } from './QueryResource';
|
||||
import { CacheConfig, GraphQLTaggedNode, OperationType } from 'relay-runtime';
|
||||
|
||||
export function useLazyLoadQuery<TQuery extends OperationType>(
|
||||
gqlQuery: GraphQLTaggedNode,
|
||||
variables: TQuery['variables'],
|
||||
options?: {
|
||||
fetchKey?: string | number;
|
||||
fetchPolicy?: FetchPolicy;
|
||||
networkCacheConfig?: CacheConfig;
|
||||
renderPolicy_UNSTABLE?: RenderPolicy;
|
||||
},
|
||||
): TQuery['response'];
|
||||
28
types/react-relay/lib/relay-experimental/useLegacyPaginationFragment.d.ts
vendored
Normal file
28
types/react-relay/lib/relay-experimental/useLegacyPaginationFragment.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { LoadMoreFn, UseLoadMoreFunctionArgs } from './useLoadMoreFunction';
|
||||
import { RefetchFnDynamic } from './useRefetchableFragmentNode';
|
||||
import { GraphQLResponse, GraphQLTaggedNode, Observer, OperationType } from 'relay-runtime';
|
||||
|
||||
export interface ReturnType<TQuery extends OperationType, TKey, TFragmentData> {
|
||||
data: TFragmentData;
|
||||
loadNext: LoadMoreFn;
|
||||
loadPrevious: LoadMoreFn;
|
||||
hasNext: boolean;
|
||||
hasPrevious: boolean;
|
||||
isLoadingNext: boolean;
|
||||
isLoadingPrevious: boolean;
|
||||
refetch: RefetchFnDynamic<TQuery, TKey>;
|
||||
}
|
||||
|
||||
export type $Call<Fn extends (...args: any[]) => any> = Fn extends (arg: any) => infer RT ? RT : never;
|
||||
|
||||
export type NonNullableReturnType<T extends { readonly ' $data'?: unknown }> = (arg: T) => NonNullable<T[' $data']>;
|
||||
export type NullableReturnType<T extends { readonly ' $data'?: unknown | null }> = (arg: T) => T[' $data'] | null;
|
||||
|
||||
export function useLegacyPaginationFragment<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly ' $data'?: unknown | null }
|
||||
>(
|
||||
fragmentInput: GraphQLTaggedNode,
|
||||
parentFragmentRef: TKey,
|
||||
): // tslint:disable-next-line no-unnecessary-generics
|
||||
ReturnType<TQuery, TKey, $Call<NonNullableReturnType<TKey> & NullableReturnType<TKey>>>;
|
||||
45
types/react-relay/lib/relay-experimental/useLoadMoreFunction.d.ts
vendored
Normal file
45
types/react-relay/lib/relay-experimental/useLoadMoreFunction.d.ts
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
ConcreteRequest,
|
||||
Disposable,
|
||||
GraphQLResponse,
|
||||
Observer,
|
||||
ReaderFragment,
|
||||
ReaderPaginationMetadata,
|
||||
RequestDescriptor,
|
||||
} from 'relay-runtime';
|
||||
|
||||
export type Direction = 'forward' | 'backward';
|
||||
|
||||
export type LoadMoreFn = (
|
||||
count: number,
|
||||
options?: {
|
||||
onComplete?: (arg: Error | null) => void;
|
||||
},
|
||||
) => Disposable;
|
||||
|
||||
export interface UseLoadMoreFunctionArgs {
|
||||
direction: Direction;
|
||||
fragmentNode: ReaderFragment;
|
||||
fragmentIdentifier: string;
|
||||
fragmentOwner: RequestDescriptor | ReadonlyArray<RequestDescriptor | null> | null;
|
||||
fragmentData: unknown;
|
||||
connectionPathInFragmentData: ReadonlyArray<string | number>;
|
||||
fragmentRefPathInResponse: ReadonlyArray<string | number>;
|
||||
paginationRequest: ConcreteRequest;
|
||||
paginationMetadata: ReaderPaginationMetadata;
|
||||
componentDisplayName: string;
|
||||
observer: Observer<GraphQLResponse>;
|
||||
onReset: () => void;
|
||||
}
|
||||
|
||||
export function useLoadMoreFunction(args: UseLoadMoreFunctionArgs): [LoadMoreFn, boolean, () => void];
|
||||
|
||||
export function getConnectionState(
|
||||
direction: Direction,
|
||||
fragmentNode: ReaderFragment,
|
||||
fragmentData: unknown,
|
||||
connectionPathInFragmentData: ReadonlyArray<string | number>,
|
||||
): {
|
||||
cursor: string | null;
|
||||
hasMore: boolean;
|
||||
};
|
||||
8
types/react-relay/lib/relay-experimental/usePreloadedQuery.d.ts
vendored
Normal file
8
types/react-relay/lib/relay-experimental/usePreloadedQuery.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { GraphQLTaggedNode, OperationType } from 'relay-runtime';
|
||||
|
||||
import { PreloadedQuery } from './EntryPointTypes';
|
||||
|
||||
export function usePreloadedQuery<TQuery extends OperationType>(
|
||||
gqlQuery: GraphQLTaggedNode,
|
||||
preloadedQuery: PreloadedQuery<TQuery>,
|
||||
): TQuery['response'];
|
||||
18
types/react-relay/lib/relay-experimental/useRefetchableFragment.d.ts
vendored
Normal file
18
types/react-relay/lib/relay-experimental/useRefetchableFragment.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { RefetchFnDynamic } from './useRefetchableFragmentNode';
|
||||
import { GraphQLTaggedNode, OperationType } from 'relay-runtime';
|
||||
|
||||
export type $Call<Fn extends (...args: any[]) => any> = Fn extends (arg: any) => infer RT ? RT : never;
|
||||
|
||||
export type NonNullableReturnType<T extends { readonly ' $data'?: unknown }> = (arg: T) => NonNullable<T[' $data']>;
|
||||
export type NullableReturnType<T extends { readonly ' $data'?: unknown | null }> = (arg: T) => T[' $data'] | null;
|
||||
|
||||
export type ReturnType<TQuery extends OperationType, TKey extends { readonly ' $data'?: unknown | null }> = [
|
||||
$Call<NonNullableReturnType<TKey> & NullableReturnType<TKey>>,
|
||||
RefetchFnDynamic<TQuery, TKey>,
|
||||
];
|
||||
|
||||
export function useRefetchableFragment<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly ' $data'?: unknown | null }
|
||||
// tslint:disable-next-line:no-unnecessary-generics
|
||||
>(fragmentInput: GraphQLTaggedNode, fragmentRef: TKey): ReturnType<TQuery, TKey>;
|
||||
124
types/react-relay/lib/relay-experimental/useRefetchableFragmentNode.d.ts
vendored
Normal file
124
types/react-relay/lib/relay-experimental/useRefetchableFragmentNode.d.ts
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
import { Disposable, OperationType, IEnvironment, Variables, ReaderFragment } from 'relay-runtime';
|
||||
|
||||
import { FetchPolicy, RenderPolicy } from './QueryResource';
|
||||
|
||||
export type RefetchFn<TQuery extends OperationType, TOptions = Options> = RefetchFnExact<TQuery, TOptions>;
|
||||
|
||||
export type RefetchFnDynamic<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly [key: string]: any } | null,
|
||||
TOptions = Options
|
||||
> = RefetchInexactDynamicResponse<TQuery, TOptions> & RefetchExactDynamicResponse<TQuery, TOptions>;
|
||||
|
||||
export type RefetchInexact<TQuery extends OperationType, TOptions> = (
|
||||
data?: unknown,
|
||||
) => RefetchFnInexact<TQuery, TOptions>;
|
||||
export type RefetchInexactDynamicResponse<TQuery extends OperationType, TOptions> = ReturnType<
|
||||
RefetchInexact<TQuery, TOptions>
|
||||
>;
|
||||
|
||||
export type RefetchExact<TQuery extends OperationType, TOptions> = (
|
||||
data?: unknown | null,
|
||||
) => RefetchFnExact<TQuery, TOptions>;
|
||||
export type RefetchExactDynamicResponse<TQuery extends OperationType, TOptions> = ReturnType<
|
||||
RefetchExact<TQuery, TOptions>
|
||||
>;
|
||||
|
||||
export type RefetchFnBase<TVars, TOptions> = (vars: TVars, options?: TOptions) => Disposable;
|
||||
|
||||
export type RefetchFnExact<TQuery extends OperationType, TOptions = Options> = RefetchFnBase<
|
||||
TQuery['variables'],
|
||||
TOptions
|
||||
>;
|
||||
export type RefetchFnInexact<TQuery extends OperationType, TOptions = Options> = RefetchFnBase<
|
||||
TQuery['variables'],
|
||||
TOptions
|
||||
>;
|
||||
|
||||
export interface ReturnTypeNode<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly [key: string]: any } | null,
|
||||
TOptions = Options
|
||||
> {
|
||||
fragmentData: unknown;
|
||||
fragmentRef: unknown;
|
||||
refetch: RefetchFnDynamic<TQuery, TKey, TOptions>;
|
||||
disableStoreUpdates: () => void;
|
||||
enableStoreUpdates: () => void;
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
fetchPolicy?: FetchPolicy;
|
||||
onComplete?: (arg: Error | null) => void;
|
||||
}
|
||||
|
||||
export interface InternalOptions extends Options {
|
||||
__environment?: IEnvironment;
|
||||
renderPolicy?: RenderPolicy;
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| {
|
||||
type: string;
|
||||
environment: IEnvironment;
|
||||
fragmentIdentifier: string;
|
||||
}
|
||||
| {
|
||||
type: string;
|
||||
refetchVariables: Variables;
|
||||
fetchPolicy?: FetchPolicy;
|
||||
renderPolicy?: RenderPolicy;
|
||||
onComplete?: (args: Error | null) => void;
|
||||
environment: IEnvironment;
|
||||
};
|
||||
|
||||
export interface RefetchState {
|
||||
fetchPolicy: FetchPolicy | undefined;
|
||||
renderPolicy: RenderPolicy | undefined;
|
||||
mirroredEnvironment: IEnvironment;
|
||||
mirroredFragmentIdentifier: string;
|
||||
onComplete: ((arg: Error | null) => void) | undefined;
|
||||
refetchEnvironment?: IEnvironment | null;
|
||||
refetchVariables?: Variables | null;
|
||||
}
|
||||
|
||||
export interface DebugIDandTypename {
|
||||
id: string;
|
||||
typename: string;
|
||||
}
|
||||
|
||||
export function reducer(state: RefetchState, action: Action): RefetchState;
|
||||
|
||||
export function useRefetchableFragmentNode<
|
||||
TQuery extends OperationType,
|
||||
TKey extends { readonly [key: string]: any } | null
|
||||
>(
|
||||
fragmentNode: ReaderFragment,
|
||||
parentFragmentRef: unknown,
|
||||
componentDisplayName: string,
|
||||
): // tslint:disable-next-line:no-unnecessary-generics
|
||||
ReturnTypeNode<TQuery, TKey, InternalOptions>;
|
||||
|
||||
export function useRefetchFunction<TQuery extends OperationType>(
|
||||
fragmentNode: any,
|
||||
parentFragmentRef: any,
|
||||
fragmentIdentifier: any,
|
||||
fragmentRefPathInResponse: any,
|
||||
fragmentData: any,
|
||||
refetchGenerationRef: any,
|
||||
dispatch: any,
|
||||
disposeFetch: any,
|
||||
componentDisplayName: any,
|
||||
): // tslint:disable-next-line:no-unnecessary-generics
|
||||
RefetchFn<TQuery, InternalOptions>;
|
||||
|
||||
export function readQuery(
|
||||
environment: any,
|
||||
query: any,
|
||||
fetchPolicy: any,
|
||||
renderPolicy: any,
|
||||
refetchGeneration: any,
|
||||
componentDisplayName: any,
|
||||
{ start, complete }: any,
|
||||
profilerContext: any,
|
||||
): any;
|
||||
3
types/react-relay/lib/relay-experimental/useRelayEnvironment.d.ts
vendored
Normal file
3
types/react-relay/lib/relay-experimental/useRelayEnvironment.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { Environment } from 'relay-runtime';
|
||||
|
||||
export function useRelayEnvironment(): Environment;
|
||||
400
types/react-relay/test/relay-experimental-tests.tsx
Normal file
400
types/react-relay/test/relay-experimental-tests.tsx
Normal file
@@ -0,0 +1,400 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Environment, RecordSource, Store, Network, commitMutation, FragmentRefs } from 'relay-runtime';
|
||||
import {
|
||||
fetchQuery,
|
||||
graphql,
|
||||
RelayEnvironmentProvider,
|
||||
useRelayEnvironment,
|
||||
preloadQuery,
|
||||
usePreloadedQuery,
|
||||
useLazyLoadQuery,
|
||||
useFragment,
|
||||
useRefetchableFragment,
|
||||
usePaginationFragment,
|
||||
} from 'react-relay/hooks';
|
||||
|
||||
const source = new RecordSource();
|
||||
const store = new Store(source);
|
||||
|
||||
function cacheHandler(operation: any, variables: { [key: string]: string }, cacheConfig: {}) {
|
||||
return fetch('/graphql', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
query: operation.text, // GraphQL text from input
|
||||
variables,
|
||||
}),
|
||||
}).then((response: any) => {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
const network = Network.create(cacheHandler);
|
||||
|
||||
const environment = new Environment({
|
||||
network,
|
||||
store,
|
||||
});
|
||||
|
||||
const query = graphql`
|
||||
query SomeQuery {
|
||||
someType
|
||||
}
|
||||
`;
|
||||
|
||||
const variables = {};
|
||||
|
||||
/**
|
||||
* Test of fetchQuery
|
||||
*/
|
||||
const dispose = fetchQuery(environment, query, variables).subscribe({
|
||||
start: subsctiption => {},
|
||||
next: payload => {},
|
||||
error: (error: Error) => {},
|
||||
complete: () => {},
|
||||
unsubscribe: subscription => {},
|
||||
});
|
||||
|
||||
dispose.unsubscribe();
|
||||
|
||||
interface AppQueryVariables {
|
||||
id: string;
|
||||
}
|
||||
interface AppQueryResponse {
|
||||
readonly user: {
|
||||
readonly name: string;
|
||||
} | null;
|
||||
}
|
||||
interface AppQuery {
|
||||
readonly response: AppQueryResponse;
|
||||
readonly variables: AppQueryVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of RelayEnvironmentProvider
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#relayenvironmentprovider
|
||||
*/
|
||||
function Provider() {
|
||||
return (
|
||||
<RelayEnvironmentProvider environment={environment}>
|
||||
<div />
|
||||
</RelayEnvironmentProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of useRelayEnvironment
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#userelayenvironment
|
||||
*/
|
||||
function RelayEnvironment() {
|
||||
const environment = useRelayEnvironment();
|
||||
|
||||
const handler = React.useCallback(() => {
|
||||
const mutation = graphql`
|
||||
mutation AddTodoMutation($input: AddTodoInput!) {
|
||||
addTodo(input: $input) {
|
||||
todoEdge {
|
||||
__typename
|
||||
cursor
|
||||
node {
|
||||
complete
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
viewer {
|
||||
id
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
commitMutation(environment, { mutation, variables: {} });
|
||||
}, [environment]);
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<div />
|
||||
</React.Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests of usePreloadedQuery
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#usepreloadedquery
|
||||
*/
|
||||
function PreloadedQuery() {
|
||||
const appQuery = graphql`
|
||||
query AppQuery($id: ID!) {
|
||||
user(id: $id) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const result = preloadQuery<AppQuery>(environment, appQuery, { id: '4' }, { fetchPolicy: 'store-or-network' });
|
||||
|
||||
return function App() {
|
||||
const data = usePreloadedQuery(query, result);
|
||||
|
||||
if (!data.user) return;
|
||||
return <h1>{data.user.name}</h1>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for useLazyLoadQuery
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#uselazyloadquery
|
||||
*/
|
||||
function LazyLoadQuery() {
|
||||
return function App() {
|
||||
const data = useLazyLoadQuery<AppQuery>(
|
||||
graphql`
|
||||
query AppQuery($id: ID!) {
|
||||
user(id: $id) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ id: '4' },
|
||||
{ fetchPolicy: 'store-and-network', networkCacheConfig: { force: true } },
|
||||
);
|
||||
|
||||
return <h1>{data.user!.name}</h1>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for useFragment
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#usefragment
|
||||
*/
|
||||
function NonNullableFragment() {
|
||||
interface UserComponent_user {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly profile_picture: {
|
||||
readonly uri: string;
|
||||
};
|
||||
readonly ' $refType': 'UserComponent_user';
|
||||
}
|
||||
type UserComponent_user$data = UserComponent_user;
|
||||
interface UserComponent_user$key {
|
||||
readonly ' $data'?: UserComponent_user$data;
|
||||
readonly ' $fragmentRefs': FragmentRefs<'UserComponent_user'>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
user: UserComponent_user$key;
|
||||
}
|
||||
|
||||
return function UserComponent(props: Props) {
|
||||
const data = useFragment(
|
||||
graphql`
|
||||
fragment UserComponent_user on User {
|
||||
name
|
||||
profile_picture(scale: 2) {
|
||||
uri
|
||||
}
|
||||
}
|
||||
`,
|
||||
props.user,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{data.name}</h1>
|
||||
<div>
|
||||
<img src={data.profile_picture.uri} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
function NullableFragment() {
|
||||
interface UserComponent_user {
|
||||
readonly id: string;
|
||||
readonly name: string | null;
|
||||
readonly profile_picture: {
|
||||
readonly uri: string | null;
|
||||
} | null;
|
||||
readonly ' $refType': 'UserComponent_user';
|
||||
}
|
||||
type UserComponent_user$data = UserComponent_user;
|
||||
interface UserComponent_user$key {
|
||||
readonly ' $data'?: UserComponent_user$data;
|
||||
readonly ' $fragmentRefs': FragmentRefs<'UserComponent_user'>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
user: UserComponent_user$key;
|
||||
}
|
||||
|
||||
return function UserComponent(props: Props) {
|
||||
const data = useFragment(
|
||||
graphql`
|
||||
fragment UserComponent_user on User {
|
||||
name
|
||||
profile_picture(scale: 2) {
|
||||
uri
|
||||
}
|
||||
}
|
||||
`,
|
||||
props.user,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{data.name}</h1>
|
||||
<div>
|
||||
<img src={data.profile_picture!.uri || undefined} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for useRefetchableFragment
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#userefetchablefragment
|
||||
*/
|
||||
function RefetchableFragment() {
|
||||
interface CommentBodyRefetchQueryVariables {
|
||||
lang?: string | null;
|
||||
id?: string | null;
|
||||
}
|
||||
interface CommentBodyRefetchQueryResponse {
|
||||
readonly node: {
|
||||
readonly ' $fragmentRefs': FragmentRefs<'CommentBody_comment'>;
|
||||
} | null;
|
||||
}
|
||||
interface CommentBodyRefetchQuery {
|
||||
readonly response: CommentBodyRefetchQueryResponse;
|
||||
readonly variables: CommentBodyRefetchQueryVariables;
|
||||
}
|
||||
|
||||
interface CommentBody_comment {
|
||||
readonly body: {
|
||||
readonly text: string;
|
||||
} | null;
|
||||
readonly id: string | null;
|
||||
readonly ' $refType': 'CommentBody_comment';
|
||||
}
|
||||
type CommentBody_comment$data = CommentBody_comment;
|
||||
interface CommentBody_comment$key {
|
||||
readonly ' $data'?: CommentBody_comment$data;
|
||||
readonly ' $fragmentRefs': FragmentRefs<'CommentBody_comment'>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
comment: CommentBody_comment$key;
|
||||
}
|
||||
|
||||
return function CommentBody(props: Props) {
|
||||
const [data, refetch] = useRefetchableFragment<CommentBodyRefetchQuery, CommentBody_comment$key>(
|
||||
graphql`
|
||||
fragment CommentBody_comment on Comment @refetchable(queryName: "CommentBodyRefetchQuery") {
|
||||
body(lang: $lang) {
|
||||
text
|
||||
}
|
||||
}
|
||||
`,
|
||||
props.comment,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>{data!.body!.text}</p>
|
||||
<button onClick={() => refetch({ lang: 'SPANISH' }, { fetchPolicy: 'store-or-network' })}>
|
||||
Translate Comment
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for usePaginationFragment
|
||||
* see https://relay.dev/docs/en/experimental/api-reference#userefetchablefragment
|
||||
*/
|
||||
function PaginationFragment() {
|
||||
interface FriendsListPaginationQueryVariables {
|
||||
count?: number;
|
||||
cursor?: string;
|
||||
id: string;
|
||||
}
|
||||
interface FriendsListPaginationQueryResponse {
|
||||
readonly node: {
|
||||
readonly ' $fragmentRefs': FragmentRefs<'FriendsListComponent_user'>;
|
||||
};
|
||||
}
|
||||
interface FriendsListPaginationQuery {
|
||||
readonly response: FriendsListPaginationQueryResponse;
|
||||
readonly variables: FriendsListPaginationQueryVariables;
|
||||
}
|
||||
|
||||
interface FriendsListComponent_user {
|
||||
readonly name: string;
|
||||
readonly friends: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly name: string;
|
||||
readonly age: number;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly id: string;
|
||||
readonly ' $refType': 'FriendsListComponent_user';
|
||||
}
|
||||
type FriendsListComponent_user$data = FriendsListComponent_user;
|
||||
interface FriendsListComponent_user$key {
|
||||
readonly ' $data'?: FriendsListComponent_user$data;
|
||||
readonly ' $fragmentRefs': FragmentRefs<'FriendsListComponent_user'>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
user: FriendsListComponent_user$key;
|
||||
}
|
||||
|
||||
return function FriendsList(props: Props) {
|
||||
const {
|
||||
data,
|
||||
loadNext,
|
||||
loadPrevious,
|
||||
hasNext,
|
||||
hasPrevious,
|
||||
isLoadingNext,
|
||||
isLoadingPrevious,
|
||||
refetch, // For refetching connection
|
||||
} = usePaginationFragment<FriendsListPaginationQuery, FriendsListComponent_user$key>(
|
||||
graphql`
|
||||
fragment FriendsListComponent_user on User @refetchable(queryName: "FriendsListPaginationQuery") {
|
||||
name
|
||||
friends(first: $count, after: $cursor) @connection(key: "FriendsList_user_friends") {
|
||||
edges {
|
||||
node {
|
||||
name
|
||||
age
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
props.user,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Friends of {data!.name}:</h1>
|
||||
|
||||
{data!.friends.edges.map(({ node }) => (
|
||||
<div>
|
||||
{node.name} - {node.age}
|
||||
</div>
|
||||
))}
|
||||
|
||||
<button onClick={() => loadNext(10)}>Load more friends</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -1,25 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"lib": ["es6", "dom"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": [
|
||||
"../"
|
||||
],
|
||||
"typeRoots": ["../"],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"files": [
|
||||
"index.d.ts",
|
||||
"test/react-relay-tests.tsx"
|
||||
]
|
||||
}
|
||||
"files": ["index.d.ts", "hooks.d.ts", "test/react-relay-tests.tsx", "test/relay-experimental-tests.tsx"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user