apollo-elements / apollo-elements
🚀🌛 Use the Launch Platform 👩🚀👨🚀
בס״ד
Today I published version 0.0.1 of apollo-elements
, a collection of packages that help you create web components connected to Apollo GraphQL.
🚀🌛 Use the Launch Platform 👩🚀👨🚀
Apollo Elements handles the plumbing between web components libraries like lit-element
or hybrids
and Apollo Client, so you can concentrate on building your app.
If you're new to web components, take a 👀 at my "Let's Build Web Components" series to get up to speed:
In a component-based app, each component can derive its state from some separate state storage. For example, you can create components which connect to a Redux or MobX store and subscribe to changes to their piece of the state puzzle.
GraphQL's flexible and extensible syntax is a natural fit for component based design, and Apollo's powerful implementation lets us easily make the connection between GraphQL data and our components. Using apollo-link-state
, you can even get rid of client-side state containers like redux altogether and query your entire component state from the apollo cache.
query UserProfilePage($userId: ID) {
session @client {
token
expiresAt
id
}
user(id: $id) {
name
avatar
friends {
name
id
}
}
}
Now, with Apollo Elements, you can get up and running building connected components. You provide a GraphQL document and a custom element class that handles templating, and you're good to go.
import { ApolloQuery, html } from '@apollo-elements/lit-apollo';
// A component that uses ApolloSubscription to update
// when users go on or offline.
import './user-online-status.js';
import './loading-spinner.js';
/**
* `<user-profile-page>` Shows a user's profile, as well as a list
* of their friends which display's each one's online status via a
* GraphQL subscription.
* @extends ApolloQuery
*/
class UserProfilePage extends ApolloQuery {
render() {
const { loading, data } = this;
return (
(loading || !data) ? html`<loading-spinner></loading-spinner>`
!data.user ? : html`<login-form></login-form>`
: html`
<h1>Hello, ${data.user.name}</h1>
<profile-image src="${data.user.avatar}"></profile-image>
<h2>Who's Online?</h2>
<dl>${data.user.friends.map(({id, name}) => html`
<dt>${name}</dt>
<dd><user-online-status id="${id}"></user-online-status></dd>
`)}</dl>
`
);
}
updated() {
// get the currently logged-in user's id from the `@client` query.
const { id } = this.id;
// setting variables updates the query.
if (id) this.variables = { id };
}
}
customElements.define('user-profile-page', UserProfilePage);
Once you've added your elements to the page, set their query
property to a GraphQL document and you're set.
You can even do neat little optional tricks like defining your queries declaratively in HTML with inline GraphQL:
<user-profile-page>
<script type="application/graphql">
query UserProfilePage($userId: ID) {
session @client {
token
expiresAt
id
}
user(id: $id) {
name
avatar
friends {
name
id
}
}
}
</script>
</user-profile-page>
Cute, right?
Apollo Elements grew out of lit-apollo
, but I wasn't content with supporting a single component class. Version 0 shipped, renamed and rebranded, with support for lit-element
, GluonElement
, and hybrids
. It also's got some Polymer-style two-way binding elements so you can expose the apollo state in your templates with `` syntax.
But the goal here was to give you, the developer, more options. If none of the above are what you're looking for, Apollo Elements also provides class mixins that let you get up and running with any vanilla-like component class, or even good-old-fashioned HTMLElement
, if you really wanted.
import { ApolloMutationMixin } from '@apollo-elements/mixins';
import gql from 'graphql-tag';
const mutation = gql`
mutation SendMessage($message: String!) {
sendMessage(message: $message) {
message
date
}
}
`;
const template = document.createElement('template');
template.innerHTML = `