or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

components.mdhoc.mdhooks.mdindex.mdssr.mdtesting.md
tile.json

components.mddocs/

React Apollo Components

React Apollo components provide render prop patterns for GraphQL operations. These components use hooks internally and provide a declarative interface for data fetching.

Capabilities

Query Component

Render prop component for executing GraphQL queries with declarative patterns.

/**
 * Render prop component for GraphQL queries
 * @param props - Query component props with render function
 * @returns JSX element from children render function
 */
function Query<TData = any, TVariables = OperationVariables>(
  props: QueryComponentOptions<TData, TVariables>
): JSX.Element | null;

interface QueryComponentOptions<TData = any, TVariables = OperationVariables>
  extends QueryFunctionOptions<TData, TVariables> {
  children: (result: QueryResult<TData, TVariables>) => JSX.Element | null;
  query: DocumentNode;
}

Usage Examples:

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const GET_USERS = gql`
  query GetUsers($limit: Int) {
    users(limit: $limit) {
      id
      name
      email
    }
  }
`;

function UserList() {
  return (
    <Query
      query={GET_USERS}
      variables={{ limit: 10 }}
      fetchPolicy="cache-and-network"
    >
      {({ data, loading, error, refetch, fetchMore }) => {
        if (loading) return <div>Loading users...</div>;
        if (error) return <div>Error loading users: {error.message}</div>;

        return (
          <div>
            <button onClick={() => refetch()}>Refresh</button>
            <ul>
              {data.users.map((user) => (
                <li key={user.id}>
                  {user.name} - {user.email}
                </li>
              ))}
            </ul>
            <button
              onClick={() =>
                fetchMore({
                  variables: { limit: 10 },
                  updateQuery: (prev, { fetchMoreResult }) => {
                    if (!fetchMoreResult) return prev;
                    return {
                      users: [...prev.users, ...fetchMoreResult.users]
                    };
                  }
                })
              }
            >
              Load More
            </button>
          </div>
        );
      }}
    </Query>
  );
}

Mutation Component

Render prop component for executing GraphQL mutations with optimistic updates.

/**
 * Render prop component for GraphQL mutations
 * @param props - Mutation component props with render function
 * @returns JSX element from children render function
 */
function Mutation<TData = any, TVariables = OperationVariables>(
  props: MutationComponentOptions<TData, TVariables>
): JSX.Element | null;

interface MutationComponentOptions<TData = any, TVariables = OperationVariables>
  extends BaseMutationOptions<TData, TVariables> {
  mutation: DocumentNode;
  children: (
    mutateFunction: MutationFunction<TData, TVariables>,
    result: MutationResult<TData>
  ) => JSX.Element | null;
}

Usage Examples:

import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const CREATE_USER = gql`
  mutation CreateUser($input: UserInput!) {
    createUser(input: $input) {
      id
      name
      email
    }
  }
`;

function CreateUserForm() {
  return (
    <Mutation
      mutation={CREATE_USER}
      onCompleted={(data) => {
        console.log('User created:', data.createUser);
      }}
      onError={(error) => {
        console.error('Error creating user:', error);
      }}
    >
      {(createUser, { data, loading, error }) => (
        <form
          onSubmit={async (e) => {
            e.preventDefault();
            const formData = new FormData(e.target);
            const input = {
              name: formData.get('name'),
              email: formData.get('email')
            };

            try {
              await createUser({
                variables: { input },
                optimisticResponse: {
                  createUser: {
                    __typename: 'User',
                    id: 'temp-id',
                    ...input
                  }
                },
                update: (cache, { data }) => {
                  // Update cache with new user
                  const existingUsers = cache.readQuery({ query: GET_USERS });
                  cache.writeQuery({
                    query: GET_USERS,
                    data: {
                      users: [...existingUsers.users, data.createUser]
                    }
                  });
                }
              });
            } catch (err) {
              // Error handled by onError callback
            }
          }}
        >
          <input name="name" type="text" placeholder="Name" required />
          <input name="email" type="email" placeholder="Email" required />
          <button type="submit" disabled={loading}>
            {loading ? 'Creating...' : 'Create User'}
          </button>
          {error && <div>Error: {error.message}</div>}
          {data && <div>User created: {data.createUser.name}</div>}
        </form>
      )}
    </Mutation>
  );
}

Subscription Component

Render prop component for managing GraphQL subscriptions with real-time updates.

/**
 * Render prop component for GraphQL subscriptions
 * @param props - Subscription component props with render function
 * @returns JSX element from children render function
 */
function Subscription<TData = any, TVariables = OperationVariables>(
  props: SubscriptionComponentOptions<TData, TVariables>
): JSX.Element | null;

interface SubscriptionComponentOptions<TData = any, TVariables = OperationVariables>
  extends BaseSubscriptionOptions<TData, TVariables> {
  subscription: DocumentNode;
  children?: null | ((result: SubscriptionResult<TData>) => JSX.Element | null);
}

Usage Examples:

import React from "react";
import { Subscription } from "react-apollo";
import gql from "graphql-tag";

const MESSAGE_SUBSCRIPTION = gql`
  subscription OnMessageAdded($channelId: ID!) {
    messageAdded(channelId: $channelId) {
      id
      content
      user {
        name
      }
      createdAt
    }
  }
`;

function ChatSubscription({ channelId }) {
  return (
    <Subscription
      subscription={MESSAGE_SUBSCRIPTION}
      variables={{ channelId }}
      onSubscriptionData={({ subscriptionData }) => {
        console.log('New message received:', subscriptionData.data.messageAdded);
        // Could trigger notifications, sound effects, etc.
      }}
    >
      {({ data, loading, error }) => {
        if (loading) return <div>Connecting to live chat...</div>;
        if (error) return <div>Connection error: {error.message}</div>;

        return (
          <div>
            {data && (
              <div className="live-message">
                <div className="message-header">
                  <strong>{data.messageAdded.user.name}</strong>
                  <span className="timestamp">
                    {new Date(data.messageAdded.createdAt).toLocaleTimeString()}
                  </span>
                </div>
                <p className="message-content">{data.messageAdded.content}</p>
              </div>
            )}
          </div>
        );
      }}
    </Subscription>
  );
}

// Usage with multiple subscriptions
function MultiChannelChat({ channels }) {
  return (
    <div>
      {channels.map((channel) => (
        <div key={channel.id} className="channel">
          <h3>{channel.name}</h3>
          <ChatSubscription channelId={channel.id} />
        </div>
      ))}
    </div>
  );
}

Component Composition Examples

Combining Query and Mutation Components

import React from "react";
import { Query, Mutation } from "react-apollo";

const GET_TODOS = gql`
  query GetTodos {
    todos {
      id
      text
      completed
    }
  }
`;

const TOGGLE_TODO = gql`
  mutation ToggleTodo($id: ID!) {
    toggleTodo(id: $id) {
      id
      completed
    }
  }
`;

function TodoApp() {
  return (
    <Query query={GET_TODOS}>
      {({ data, loading, error }) => {
        if (loading) return <div>Loading todos...</div>;
        if (error) return <div>Error: {error.message}</div>;

        return (
          <Mutation mutation={TOGGLE_TODO}>
            {(toggleTodo, { loading: mutationLoading }) => (
              <ul>
                {data.todos.map((todo) => (
                  <li key={todo.id}>
                    <label>
                      <input
                        type="checkbox"
                        checked={todo.completed}
                        disabled={mutationLoading}
                        onChange={() =>
                          toggleTodo({
                            variables: { id: todo.id },
                            optimisticResponse: {
                              toggleTodo: {
                                __typename: 'Todo',
                                id: todo.id,
                                completed: !todo.completed
                              }
                            }
                          })
                        }
                      />
                      {todo.text}
                    </label>
                  </li>
                ))}
              </ul>
            )}
          </Mutation>
        );
      }}
    </Query>
  );
}