Screenshot of the live poll app (Large preview )
You should be able to play around with the app now. Go ahead and vote as many times as you want, you’ll notice the results changing in real time. In fact, if you set up another instance of this UI and point it to the same backend, you’ll be able to see results aggregated across all the instances.
So, how does this app use GraphQL? Read on.
Behind The Scenes: GraphQL
In this section, we’ll explore the GraphQL features powering the app, followed by a demonstration of the ease of integration in the next one.
The Poll Component And The Aggregated Results Graph
The poll component on the top left that fetches a poll with all of its options and captures a user’s vote in the database. Both of these operations are done using the GraphQL API. For fetching a poll’s details, we make a query (remember this from the GraphQL introduction?):
query {
poll {
id
question
options {
id
text
}
}
}
Using the Mutation component from react-apollo
, we can wire up the mutation to a HTML form such that the mutation is executed using variables optionId
and userId
when the form is submitted:
mutation vote($optionId: uuid!, $userId: uuid!) {
insert_vote(objects: [{option_id: $optionId, created_by_user_id: $userId}]) {
returning {
id
}
}
}
To show the poll results, we need to derive the count of votes per option from the data in vote table. We can create a Postgres View and track it using GraphQL Engine to make this derived data available over GraphQL.
CREATE VIEW poll_results AS
SELECT poll.id AS poll_id, o.option_id, count(*) AS votes
FROM (( SELECT vote.option_id, option.poll_id, option.text
FROM ( vote
LEFT JOIN
public.option ON ((option.id = vote.option_id)))) o
LEFT JOIN poll ON ((poll.id = o.poll_id)))
GROUP BY poll.question, o.option_id, poll.id;
The poll_results
view joins data from vote
and poll
tables to provide an aggregate count of number of votes per each option.
Using GraphQL Subscriptions over this view, react-google-charts and the subscription component from react-apollo
, we can wire up a reactive chart which updates in realtime when a new vote happens from any client.
subscription getResult($pollId: uuid!) {
poll_results(where: {poll_id: {_eq: $pollId}}) {
option {
id
text
}
votes
}
}
GraphQL API Integration
As I mentioned earlier, I used Apollo Client, an open-source SDK to integrate a ReactJS app with the GraphQL backend. Apollo Client is analogous to any HTTP client library like requests for python , the standard http module for JavaScript , and so on. It encapsulates the details of making an HTTP request (in this case POST requests). It uses the configuration (specified in src/apollo.js
) to make query/mutation/subscription requests (specified in src/GraphQL.jsx with the option to use variables that can be dynamically substituted in the JavaScript code of your REACT app) to a GraphQL endpoint. It also leverages the typed schema behind the GraphQL endpoint to provide compile/dev time validation for the aforementioned requests. Let’s see just how easy it is for a client app to make a live-query (subscription) request to the GraphQL API.
Configuring The SDK
The Apollo Client SDK needs to be pointed at a GraphQL server, so it can automatically handle the boilerplate code typically needed for such an integration. So, this is exactly what we did when we modified src/apollo.js when setting up the frontend app.
Making A GraphQL Subscription Request (Live-Query)
Define the subscription we looked at in the previous section in the src/GraphQL.jsx file:
const SUBSCRIPTION_RESULT = `
subscription getResult($pollId: uuid!) {
poll_results (
order_by: option_id_desc,
where: { poll_id: {_eq: $pollId} }
) {
option_id
option { id text }
votes
}
}`;
We’ll use this definition to wire up our React component:
export const Result = (pollId) => (
<Subscription subscription={gql`${SUBSCRIPTION_RESULT}`} variables={pollId}>
{({ loading, error, data }) => {
if (loading) return Loading...</p>;
if (error) return
One thing to note here is that the above subscription could also have been a query. Merely replacing one keyword for another gives us a “live-query”, and that’s all it takes for the Apollo Client SDK to hook this real-time API with your app. Every time there’s a new dataset from our live-query, the SDK triggers a re-render of our chart with this updated data (using the renderChart(data)
call). That’s it. It really is that simple!
Final Thoughts
In three simple steps (creating a GraphQL backend, modeling the app schema, and integrating the frontend with the GraphQL API), you can quickly wire-up a fully-functional real-time app, without getting mired in unnecessary details such as setting up a websocket connection. That right there is the power of community tooling backing an abstraction like GraphQL.
If you’ve found this interesting and want to explore GraphQL further for your next side project or production app, here are some factors you may want to use for building your GraphQL toolchain:
Performance & Scalability GraphQL is meant to be consumed directly by frontend apps (it’s no better than an ORM in the backend; real productivity benefits come from doing this). So your tooling needs to be smart about efficiently using database connections and should be able scale effortlessly.
Security It follows from above that a mature role-based access-control system is needed to authorize access to data.
Automation If you are new to the GraphQL ecosystem, handwriting a GraphQL schema and implementing a GraphQL server may seem like daunting tasks. Maximize the automation from your tooling so you can focus on the important stuff like building user-centric frontend features.
Architecture As trivial as the above efforts seem like, a production-grade app’s backend architecture may involve advanced GraphQL concepts like schema-stitching, etc. Moreover, the ability to easily generate/consume real-time APIs opens up the possibility of building asynchronous, reactive apps that are resilient and inherently scalable. Therefore, it’s critical to evaluate how GraphQL tooling can streamline your architecture.
Related Resources
You can check out a live version of the app over here .
The complete source code is available on GitHub .
If you’d like to explore the database schema and run test GraphQL queries, you can do so over here .
(rb, ra, yk, il)