Written in connection with the Write with Fauna program.
Introduction
Using a Todo Application
What we will be building
I feel the best way to learn is by doing. In this article to we will build a Todo app using URQL,
we will learn how to :
- Setup URQL with React
- Setting Fetch Options like “request headers”
- Write queries
- Write Mutation
What is URQL
URQL stands for Universal React Query Library. URQL is a GraphQL client that exposes a set of React components and hooks. It's built to be highly customizable and versatile so you can take it from getting started with your first GraphQL project all the way to building complex apps and experimenting with GraphQL clients. Please Note that we weill make use of Git , Redux , GraphQL, NodeJS and Reactstrap but we are going to concentrate fully on URQL.
You can get the finished project - URQL_TODO_APP
Prerequisite for the article
- Basic Knowledge of React
- Basic Graphql knowledge
- NodeJS Installed on your PC
- Knowledge of Redux will be a plus (as we will be using redux for state management)
- Git & GitHub knowledge
- Basic Knowledge of Redux
Getting started
Since we will be making use of the Fauna GraphQL API. Make sure you Sign up to Fauna and set up your GraphQL API. Fauna GraphQL api requires an authorization key which we will save as an Environment variable (for Security reason).
Step 1:
In the root level of your react application, create a file .env.local
. In this file, add an entry for the generated key:
REACT_APP_FAUNA_SECRET=fnAD7S71UlACBcBWehe5q06JQeDRNgJUiNTbvUoN
NOTE:
- The file should be named
.env.local
and not just.env
- Environment Variables that would be used in a react application should start with “REACT_APP_”… else they won’t be imported by default
- make sure you also have a
.gitignore
file in your project’s root directory that contains.env.local
so that your secrets won’t be added to your git repo and shared with others. - You’ll have to explicitly stop and restart your application with
yarn start
in order to see these changes take. ##
Step 2:
Install relevant packages:
Using Yarn
$ yarn add urql graphql
Or Using npm
$ npm install --save urql graphql
Update the index.js
file in the root level of the application to the code below
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createClient, Provider } from 'urql';
// Create a Urql graphql client
const client = createClient({
url: 'https://graphql.fauna.com/graphql', /// the graqhql api url
fetchOptions: { // fetch options you which to add
headers: { // request header
// authorization token imported from .env.local
authorization: `Bearer ${process.env.REACT_APP_FAUNA_SECRET}`,
},
},
});
ReactDOM.render(
<React.StrictMode>
<Provider value={client}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
Code Explanation:
-
createClient
- Create a GraphQL client to enable interaction with the GraphQL api -
fetchOptions
- This option allows us to customize the options that will be passed tofetch
when a request is sent to the given APIurl
-
Provider
- A Wrapper component that enables every other component inside it to make use of GraphQL queries that will be sent to our API -
url
- the GraphQL API url -
headers
- custom headers needed by the API , this might be needed for Authentication, Authorization, e.t.c.
If you have been following along so far, congratulations, you are ready to start writing queries and Mutations
CRUD (Create, Read, Update, Delete) Operations With URQL
After you setup URQL, the next step is to Create a todo task.
Create Task
import { useMutation } from 'urql';
/*At the top of your of your file */
// ...code
/* Inside a React component */
const CreateTodo = /* GraphQL */ `
mutation($data: TodoInput!) {
createTodo(data: $data) {
_id
name
completed
}
}
`;
const [result, createTodoItem] = useMutation(CreateTodo);
function onSumbit() {
const newItem = {
data: {
name: name,
completed: false,
},
};
createTodoItem(newItem).then((result) => {
const {
data: { createTodo },
} = result;
props.addItem(createTodo); // passing data our redux store
});
}
Code Explanation:
For a better understanding of the code I suggest you go through the The Project Repo, Navigate to src/components/itemModal.js
-
CreateTodo
- is a GraphQL mutation. You can use the GraphQL playground and Schema to structure your mutations and queries. -
useMutation
- is imported fromurql
and is used to execute GraphQL mutations. it return a tuple. -
result
- The first item in the tuple containsfetching
,error
, anddata
— it's identical since this is a common pattern of howurql
presents operation results. -
createTodoItem
- The second Item in the tuple is a function where you pass graphQL variables. Notice in the GraphQL mutation we passed$data
as a variable, and in thecreateTodoItem
function we passed data as an argument in the function call.
Get All tasks (GET)
import { useQuery } from 'urql';
/*At the top of your of your file */
// ...code
/* Inside a React component */
const [result] = useQuery({
query: `
{
allTodos {
data {
_id
name
completed
}
}
}
`,
});
const { data, fetching , error} = result;
Code Explanation:
For a better understanding of the code I suggest you go through the The Project Repo, Navigate to src/components/TodoList.js
-
useQuery
- Is used to make GraphQL query request. Similar to theuseMutation
hook, theuseQuery
hook returns a tuple but with only one Item, which is the result (response) of the query. -
result
- is the response data from a query request, it is an object with three properties,- data
- fetching
- error
-
data
- basically response data from the server -
fetching
- This is the state of the request, It is initially false, when a request is completed it updates totrue
. -
error
- This propertty contains the error message if any error occurs, it is initiallyundefined
but updates to an error message from the server if an error occurs
Mark as Completed (Update)
import { useMutation} from 'urql';
/*At the top of your of your file */
// ...code
/* Inside a React component */
const updateTodo = /* GraphQL */ `
mutation UpdateTodo($id: ID!, $data: TodoInput!) {
updateTodo(id: $id, data: $data) {
_id
name
completed
}
}
`;
const [updateResult, updateTodoItem] = useMutation(updateTodo);
const newItem = {
id: props.id,
data: {
name,
completed: props.completed,
},
};
updateTodoItem(newItem).then((result) => {
// result here is similar to updateResult (first item returned by useMutation)
const {
data: { updateTodo },
} = result;
});
Code Explanation:
For a better understanding of the code I suggest you go through the The Project Repo, Navigate to src/components/updateItemModal.js
.
-
UpdateTodo
- is a GraphQL mutation. You can use the GraphQL playground and Schema to structure your mutations and queries. -
useMutation
- is imported fromurql
and is used to execute GraphQL mutations. it return a tuple. -
result
andupdateResult
- The first item in the tuple containsfetching
,error
, anddata
— it's identical since this is a common pattern of howurql
presents operation results. -
updateTodoItem
- The second Item in the tuple is a function where you pass graphQL variables. Notice in the GraphQL mutation we passed$id
and$data
as variables, and in theupdateTodoItem
function we passed them as arguments in the function call.
Delete tasks (DELETE)
import { useMutation} from 'urql';
/*At the top of your of your file */
// ...code
/* Inside a React component */
const deleteTodo = /* GraphQL */ `
mutation DeleteTodo($id: ID!) {
deleteTodo(id: $id) {
_id
name
}
}
`;
const [, deleteTask] = useMutation(deleteTodo);
deleteTask(data).then((result) => {
const {
data: {
deleteTodo: { _id: deletedDataId },
},
} = result;
});
For a better understanding of the code I suggest you go through the The Project Repo, Navigate to src/components/DeleteButton.js
.
-
deleteTodo
- is a GraphQL mutation. You can use the GraphQL playground and Schema to structure your mutations and queries. -
useMutation
- is imported fromurql
and is used to execute GraphQL mutations. it return a tuple. -
result
- The first item in the tuple containsfetching
,error
, anddata
— it's identical since this is a common pattern of howurql
presents operation results. -
deleteTask
- The second Item in the tuple is a function where you pass GraphQL variables. Notice in the GraphQL mutation we passed$id
as a variable, and in thedeleteTask
function we passed them as arguments in the function call.
Conclusion
In this Article we learnt How to Setup URQL with React, create data, fetch data, update data and delete data. URQL is a really wonderful library to look into, You can checkout URQL documentation for more Information.
Top comments (1)
Is it ok to expose your API key in the client like this?