[relay] Cleanup of where types are defined and scope tests.

This commit is contained in:
Eloy Durán
2018-02-06 15:59:16 +01:00
parent be38f831c2
commit c41956752f
4 changed files with 185 additions and 155 deletions
+1 -2
View File
@@ -4,14 +4,13 @@ import {
RelayPaginationProp as RelayModernPaginationProp,
RelayRefetchProp as RelayModernRefetchProp,
} from "./index";
export { ConcreteFragment, ConcreteRequest, ConcreteBatchRequest } from "relay-runtime";
import * as RelayRuntimeTypes from "relay-runtime";
import { RelayEnvironmentInterface } from "./classic";
// ~~~~~~~~~~~~~~~~~~~~~
// Maybe Fix
// ~~~~~~~~~~~~~~~~~~~~~
export type ConcreteFragment = any;
export type ConcreteBatch = any;
export type ConcreteFragmentDefinition = object;
export type ConcreteOperationDefinition = object;
+12 -18
View File
@@ -11,6 +11,7 @@ export {
commitLocalUpdate,
commitRelayModernMutation as commitMutation,
fetchRelayModernQuery as fetchQuery,
GraphQLTaggedNode,
requestRelaySubscription as requestSubscription,
} from "relay-runtime";
@@ -20,8 +21,6 @@ import * as RelayRuntimeTypes from "relay-runtime";
// ~~~~~~~~~~~~~~~~~~~~~
// Maybe Fix
// ~~~~~~~~~~~~~~~~~~~~~
export type ConcreteFragment = any;
export type ConcreteBatch = any;
export type ConcreteFragmentDefinition = object;
export type ConcreteOperationDefinition = object;
@@ -39,24 +38,19 @@ export interface RelayProp {
export function RelayQL(strings: string[], ...substitutions: any[]): RelayRuntimeTypes.RelayConcreteNode;
// ~~~~~~~~~~~~~~~~~~~~~
// RelayModernGraphQLTag
// ReactRelayTypes
// ~~~~~~~~~~~~~~~~~~~~~
export interface GeneratedNodeMap {
[key: string]: GraphQLTaggedNode;
[key: string]: RelayRuntimeTypes.GraphQLTaggedNode;
}
export type GraphQLTaggedNode =
| (() => ConcreteFragment | ConcreteBatch)
| {
modern(): ConcreteFragment | ConcreteBatch;
classic(relayQL: typeof RelayQL): ConcreteFragmentDefinition | ConcreteOperationDefinition;
};
/**
* Runtime function to correspond to the `graphql` tagged template function.
* All calls to this function should be transformed by the plugin.
*/
export interface GraphqlInterface {
(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
experimental(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
(strings: string[] | TemplateStringsArray): RelayRuntimeTypes.GraphQLTaggedNode;
experimental(strings: string[] | TemplateStringsArray): RelayRuntimeTypes.GraphQLTaggedNode;
}
export const graphql: GraphqlInterface;
@@ -66,7 +60,7 @@ export const graphql: GraphqlInterface;
export interface QueryRendererProps {
cacheConfig?: RelayRuntimeTypes.CacheConfig;
environment: RelayRuntimeTypes.Environment;
query: GraphQLTaggedNode;
query: RelayRuntimeTypes.GraphQLTaggedNode;
render(readyState: ReadyState): React.ReactElement<any> | undefined | null;
variables: RelayRuntimeTypes.Variables;
rerunParamExperimental?: RelayRuntimeTypes.RerunParam;
@@ -87,7 +81,7 @@ export class QueryRenderer extends ReactRelayQueryRenderer {}
// ~~~~~~~~~~~~~~~~~~~~~
export function createFragmentContainer<T>(
Component: React.ComponentType<T>,
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap
fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap
): React.ComponentType<T>;
// ~~~~~~~~~~~~~~~~~~~~~
@@ -130,11 +124,11 @@ export interface ConnectionConfig<T> {
paginationInfo: { count: number; cursor?: string },
fragmentVariables: RelayRuntimeTypes.Variables
): RelayRuntimeTypes.Variables;
query: GraphQLTaggedNode;
query: RelayRuntimeTypes.GraphQLTaggedNode;
}
export function createPaginationContainer<T>(
Component: React.ComponentType<T>,
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap,
connectionConfig: ConnectionConfig<T>
): React.ComponentType<T>;
@@ -157,6 +151,6 @@ export type RelayRefetchProp = RelayProp & {
};
export function createRefetchContainer<T>(
Component: React.ComponentType<T>,
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
taggedNode: GraphQLTaggedNode
fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap,
taggedNode: RelayRuntimeTypes.GraphQLTaggedNode
): React.ComponentType<T>;
+155 -129
View File
@@ -10,7 +10,8 @@ import {
requestSubscription,
QueryRenderer,
RelayRefetchProp,
RelayPaginationProp
RelayPaginationProp,
RelayProp
} from "react-relay";
// ~~~~~~~~~~~~~~~~~~~~~
@@ -54,160 +55,185 @@ const MyQueryRenderer = (props: { name: string }) => (
// ~~~~~~~~~~~~~~~~~~~~~
// Modern FragmentContainer
// ~~~~~~~~~~~~~~~~~~~~~
const MyFragmentContainer = createFragmentContainer(
class TodoListView extends React.Component {
render() {
return <div />;
}
},
{
item: graphql`
fragment TodoItem_item on Todo {
text
isComplete
}
`,
() => {
interface Props {
relay: RelayProp;
publicProp: string;
}
);
class TodoListView extends React.Component<Props> {
render() {
this.props.relay.environment;
return <div>{this.props.publicProp}</div>;
}
}
const MyFragmentContainer = createFragmentContainer(
TodoListView,
{
item: graphql`
fragment TodoItem_item on Todo {
text
isComplete
}
`,
}
);
};
// ~~~~~~~~~~~~~~~~~~~~~
// Modern RefetchContainer
// ~~~~~~~~~~~~~~~~~~~~~
interface StoryInterface {
id: string;
}
interface FeedStoriesProps {
relay: RelayRefetchProp;
feed: {
stories: { edges: Array<{ node: StoryInterface }> };
};
}
class Story extends React.Component<{ story: StoryInterface }> {}
class FeedStories extends React.Component<FeedStoriesProps> {
render() {
return (
<div>
{this.props.feed.stories.edges.map(edge => <Story story={edge.node} key={edge.node.id} />)}
<button onClick={() => this._loadMore} title="Load More" />
</div>
);
() => {
interface StoryInterface {
id: string;
}
interface Props {
relay: RelayRefetchProp;
loadMoreTitle: string;
feed: {
stories: { edges: Array<{ node: StoryInterface }> };
};
}
class Story extends React.Component<{ story: StoryInterface }> {}
class FeedStories extends React.Component<Props> {
render() {
return (
<div>
{this.props.feed.stories.edges.map(edge => <Story story={edge.node} key={edge.node.id} />)}
<button onClick={() => this._loadMore} title={this.props.loadMoreTitle} />
</div>
);
}
_loadMore() {
// Increments the number of stories being rendered by 10.
const refetchVariables = (fragmentVariables: { count: number }) => ({
count: fragmentVariables.count + 10,
});
this.props.relay.refetch(refetchVariables);
}
}
_loadMore() {
// Increments the number of stories being rendered by 10.
const refetchVariables = (fragmentVariables: { count: number }) => ({
count: fragmentVariables.count + 10,
});
this.props.relay.refetch(refetchVariables);
}
}
const FeedRefetchContainer = createRefetchContainer(
FeedStories,
{
feed: graphql.experimental`
fragment FeedStories_feed on Feed @argumentDefinitions(count: { type: "Int", defaultValue: 10 }) {
stories(first: $count) {
edges {
node {
id
...Story_story
const FeedRefetchContainer = createRefetchContainer(
FeedStories,
{
feed: graphql.experimental`
fragment FeedStories_feed on Feed @argumentDefinitions(count: { type: "Int", defaultValue: 10 }) {
stories(first: $count) {
edges {
node {
id
...Story_story
}
}
}
}
`,
},
graphql.experimental`
query FeedStoriesRefetchQuery($count: Int) {
feed {
...FeedStories_feed @arguments(count: $count)
}
}
`,
},
graphql.experimental`
query FeedStoriesRefetchQuery($count: Int) {
feed {
...FeedStories_feed @arguments(count: $count)
}
}
`
);
`
);
};
// ~~~~~~~~~~~~~~~~~~~~~
// Modern PaginationContainer
// ~~~~~~~~~~~~~~~~~~~~~
interface FeedProps {
user: { feed: { edges: Array<{ node: StoryInterface }> } };
relay: RelayPaginationProp;
}
class Feed extends React.Component<FeedProps> {
render() {
return (
<div>
{this.props.user.feed.edges.map(edge => <Story story={edge.node} key={edge.node.id} />)}
<button onClick={() => this._loadMore()} title="Load More" />
</div>
);
}
_loadMore() {
if (!this.props.relay.hasMore() || this.props.relay.isLoading()) {
return;
() => {
interface StoryInterface {
id: string;
}
class Story extends React.Component<{ story: StoryInterface }> {}
interface Props {
relay: RelayPaginationProp;
loadMoreTitle: string;
user: { feed: { edges: Array<{ node: StoryInterface }> } };
}
class Feed extends React.Component<Props> {
render() {
return (
<div>
{this.props.user.feed.edges.map(edge => <Story story={edge.node} key={edge.node.id} />)}
<button onClick={() => this._loadMore()} title={this.props.loadMoreTitle} />
</div>
);
}
this.props.relay.loadMore(
10, // Fetch the next 10 feed items
e => {
console.log(e);
_loadMore() {
if (!this.props.relay.hasMore() || this.props.relay.isLoading()) {
return;
}
);
}
}
const FeedPaginationContainer = createPaginationContainer(
Feed,
{
user: graphql`
fragment Feed_user on User {
feed(
first: $count
after: $cursor
orderby: $orderBy # other variables
) @connection(key: "Feed_feed") {
edges {
node {
id
...Story_story
this.props.relay.loadMore(
10, // Fetch the next 10 feed items
e => {
console.log(e);
}
);
}
}
const FeedPaginationContainer = createPaginationContainer(
Feed,
{
user: graphql`
fragment Feed_user on User {
feed(
first: $count
after: $cursor
orderby: $orderBy # other variables
) @connection(key: "Feed_feed") {
edges {
node {
id
...Story_story
}
}
}
}
}
`,
},
{
direction: "forward",
getConnectionFromProps(props) {
return props.user && props.user.feed;
`,
},
getFragmentVariables(prevVars, totalCount) {
return {
...prevVars,
count: totalCount,
};
},
getVariables(props, { count, cursor }, fragmentVariables) {
return {
count,
cursor,
// in most cases, for variables other than connection filters like
// `first`, `after`, etc. you may want to use the previous values.
orderBy: fragmentVariables.orderBy,
};
},
query: graphql`
query FeedPaginationQuery($count: Int!, $cursor: String, $orderby: String!) {
user {
# You could reference the fragment defined previously.
...Feed_user
{
direction: "forward",
getConnectionFromProps(props) {
return props.user && props.user.feed;
},
getFragmentVariables(prevVars, totalCount) {
return {
...prevVars,
count: totalCount,
};
},
getVariables(props, { count, cursor }, fragmentVariables) {
return {
count,
cursor,
// in most cases, for variables other than connection filters like
// `first`, `after`, etc. you may want to use the previous values.
orderBy: fragmentVariables.orderBy,
};
},
query: graphql`
query FeedPaginationQuery($count: Int!, $cursor: String, $orderby: String!) {
user {
# You could reference the fragment defined previously.
...Feed_user
}
}
}
`,
`,
}
);
}
);
};
// ~~~~~~~~~~~~~~~~~~~~~
// Modern Mutations
+17 -6
View File
@@ -17,8 +17,6 @@ export type RelayConcreteNode = any;
export type RelayMutationTransaction = any;
export type RelayMutationRequest = any;
export type RelayQueryRequest = any;
export type ConcreteFragment = any;
export type ConcreteBatch = any;
export type ConcreteFragmentDefinition = object;
export type ConcreteOperationDefinition = object;
@@ -32,6 +30,19 @@ export type ConcreteOperationDefinition = object;
*/
export type RelayContainer = any;
// ~~~~~~~~~~~~~~~~~~~~~
// Used in artifacts
// emitted by
// relay-compiler
// ~~~~~~~~~~~~~~~~~~~~~
// File: https://github.com/facebook/relay/blob/fe0e70f10bbcba1fff89911313ea69f24569464b/packages/relay-runtime/util/RelayConcreteNode.js
export type ConcreteFragment = any;
export type ConcreteRequest = any;
export type ConcreteBatchRequest = any;
export type RequestNode = ConcreteRequest | ConcreteBatchRequest;
// ~~~~~~~~~~~~~~~~~~~~~
// RelayQL
// ~~~~~~~~~~~~~~~~~~~~~
@@ -44,9 +55,9 @@ export interface GeneratedNodeMap {
[key: string]: GraphQLTaggedNode;
}
export type GraphQLTaggedNode =
| (() => ConcreteFragment | ConcreteBatch)
| (() => ConcreteFragment | RequestNode)
| {
modern(): ConcreteFragment | ConcreteBatch;
modern(): ConcreteFragment | RequestNode;
classic(relayQL: RelayQL): ConcreteFragmentDefinition | ConcreteOperationDefinition;
};
// ~~~~~~~~~~~~~~~~~~~~~
@@ -85,7 +96,7 @@ export interface PayloadError {
* May return an Observable or Promise of a raw server response.
*/
export function FetchFunction(
operation: ConcreteBatch,
operation: RequestNode,
variables: Variables,
cacheConfig: CacheConfig,
uploadables?: UploadableMap
@@ -99,7 +110,7 @@ export function FetchFunction(
* fourth parameter.
*/
export type SubscribeFunction = (
operation: ConcreteBatch,
operation: RequestNode,
variables: Variables,
cacheConfig: CacheConfig,
observer: LegacyObserver<QueryPayload>