import { ApolloError } from "apollo-boost"; import gql from "graphql-tag"; import { graphql } from "react-apollo"; ///////////////////////////////////////////////////////////////////// // somehow generate these interfaces based on the query and schema // ///////////////////////////////////////////////////////////////////// interface IPost { id: number; title: string; } interface IResponse { allPosts?: IPost[]; } interface IVariables { first: number; skip: number; } interface IActions { loadMorePosts: () => void; } interface IApolloResponse<R /* The response format */> { data: R & { /* the tricky part is that we have to only select some of the response fields here */ error?: ApolloError; loading: boolean; }; }; type ChildProps = IActions & IApolloResponse<IResponse>; const ALL_POST_QUERY = gql` query allPosts($first: Int!, $skip: Int!) { allPosts(first: $first, skip: $skip) { id title } } `; const withData = graphql<{}, IResponse, IVariables, ChildProps>( ALL_POST_QUERY, { options: { variables: { first: 5, skip: 0 } }, props: ({ data }): ChildProps => { return { data, loadMorePosts: () => { // do stuff here } }; } } ); const component = ({ data: { loading, error, allPosts }, loadMorePosts }: ChildProps) => { if (error) { return <div>Error loading posts.</div>; } if (loading) { return <div>Loading......</div>; } if (allPosts && allPosts.length) { return ( <div> <ul> {allPosts.map(post => <li key={post.id}>{post.title}</li>)} </ul> <button onClick={() => loadMorePosts()}>Show More</button> </div> ); } return <div>No post to show</div>; } export default withData(component)