Skip to content

Instantly share code, notes, and snippets.

@crucialfelix
Last active December 15, 2017 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crucialfelix/4515c2fcdbd9b62afe3ef8beabab3f72 to your computer and use it in GitHub Desktop.
Save crucialfelix/4515c2fcdbd9b62afe3ef8beabab3f72 to your computer and use it in GitHub Desktop.
import React from "react";
import { MessagesQuery, MessagesQueryVariables } from "../../queries";
import { graphql, QueryProps } from "react-apollo";
import Message from "./Message";
// IMPORTANT: The query is required, not imported.
const query = require("./Messages.graphql");
const POLL_INTERVAL = 7901;
/**
* This is the public interface, the attributes that you can create this component with:
*
* <Messages threadKey="xyz12345" />
*
* It is a subset of the full props that the component will see in its implementation.
*/
interface PublicProps {
threadKey: string;
}
/**
* These are the props that apollo will supply as this.props.data
*
* MessagesQuery is the interface generated from Messages.graphql
* and QueryProps is imported from react-apollo
* and includes the whole data API: .loading, .error, .fetchMore and all that:
* https://github.com/apollographql/react-apollo/blob/4ee68965840df9c7908c4cba2ac6b3a3fe383685/src/types.ts#L42
*/
interface DataProps {
data: MessagesQuery & QueryProps;
}
// This is the full props that the component sees internally.
// An intersection of the public props
type Props = PublicProps & DataProps;
/**
* Display Messages in a thread
*/
class Messages extends React.PureComponent<
Props, // full props
undefined // state: there is none on this component
> {
public render() {
// If you are still loading or if the viewer is null (not logged in etc.)
// then just return.
if (!this.props.data.viewer) {
return null;
}
return (
<div className="mw8">
{this.props.data.viewer.messages.edges.map(edge => (
<Message message={edge.node} key={edge.node.id} />
))}
</div>
);
}
}
/**
* This is a function that takes the PublicProps and returns query variables
* for the Message.graphql query.
*
* PublicProps -> MessagesQueryVariables
*
* Actually it gets the full props, but for the purposes of generating query variables you should
* only be dependant on the externally specified props. Everything else is internal apollo results and api.
*
* The MessagesQueryVariables is generated from the .graphql code so we can now guarantee that this
* function will return a correct query. The names and types of all variables must match or
* we get squiggly red lines and a lovely compile error.
*/
const queryVars = (props: PublicProps): MessagesQueryVariables => ({
threadKey: props.threadKey
});
/**
* Apollo graphql query config supplies options as a function taking props
*/
const config = {
options: props => ({
variables: queryVars(props),
// I'm going to refresh the messages every 7 seconds
pollInterval: POLL_INTERVAL
})
};
/**
* Create the final component using graphql.
*
* Note now that the props we supply the public props as the generic
* type variable. These are the props which we wish to expose to the outside world.
* So the returned component will be typed to have these typed attributes
* and politely scold you when you supply otherwise.
*/
export default graphql<MessagesQuery, PublicProps>(query, config)(Messages);
#import './Message.graphql'
# The query is named Messages so the type will be called MessagesQuery
# It accepts one query variable: threadKey which is a required String
query Messages($threadKey: String!) {
viewer {
id
messages(threadKey: $threadKey) {
edges {
node {
id
...Message
}
}
}
}
}
export type MessagesQueryVariables = {
threadKey: string;
};
export type MessagesQuery = {
viewer: {
// The ID of the object.
id: string;
// Query all messages by thread key
messages: {
edges: Array<{
// The item at the end of the edge
node: {
// The ID of the object.
id: string;
body: string;
createdOn: string;
messageType: string;
author: {
id: string;
name: string;
email: string;
phone: string;
thumb?: string;
isStaff: boolean;
pk?: number;
};
};
}>;
} | null;
} | null;
};
export type MessageFragment = {
// The ID of the object.
id: string;
body: string;
createdOn: string;
messageType: string;
author: {
id: string;
name: string;
email: string;
phone: string;
thumb?: string;
isStaff: boolean;
pk?: number;
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment