The logical tool to use when I set out to build this website - Locallog was Nextjs, I needed SEO amongst other things that a single page app did not provide and also, Nextjs is awesome.
I used an Express server with MongoDB on the backend. It was the first time I was using a GraphQL API. The popular tool I saw everywhere to query a GraphQL API on the front end was Apollo so I went straight to Nextjs’s Github page and looked up the Apollo example, I copied the entire code without checking the README. Querying the API worked, but I ran into issues because I didn’t query inside of Nextjs’s data fetching methods. If you are not familiar with them, check out the Docs.
My data wasn’t fetching at request time so it did not populate the head tag and I was getting a blank screen at some point. The whole idea of using Nextjs for SEO was defeated. I raised an issue on Github and was told to use a lighter library. I consulted Google and found a library: GraphQL Request, it is a Minimal GraphQL client supporting Node and browsers for scripts or simple apps
I will be showing you how to query and make mutations using variables. We will be building a Todo app.
First, install the library on npm (you can also use Yarn) and import ‘request’ on your page like so:
Npm i ‘graphql-request’ // in terminal
import { request } from "graphql-request"; // in your page
We will be constructing our query like so:
//request query
const TODOS = ` {
todos{
id
name
completed
date
}
}`;
Here, we query for all Todo items. First we created a variable and assigned it to our request query.
Now we would use it inside of Nextjs’ getServerSideProps, you could use getStaticProps or combine getStaticProps with getStaticPaths, read the docs on Nextjs.org.
export async function getServerSideProps() {
//'request' from ‘graphql-request’ library
const res = await request(‘/api/graphiql’, TODOS);
const data = res.todos;
return {
props: {
data //Pass Data in props
},
};
}
//pass data into component
function Index({ data }) {
return (
<div>
...use data here
{data.id}
</div>
)
};
It’s that simple, we passed in two arguments in request(‘/api/graphql’,TODOS)
. ‘/api/graphiql’
is our request endpoint and ‘TODOS’
is the variable assigned to our query.
Full code:
import { request } from"graphql-request";
const TODOS = `{
todos{
id
name
completed
date
}
}
`;
export async function getServerSideProps(){
const res = await request(‘/api/graphql’,TODOS);
const data = res.todos;
return {
props: {
data
},
};
}
function Index({ data }) {
return (
<div>
{data.id}
</div>
)
};
Now Let's query for a single Todo Item
const TODO = `
query todo($id: String!) { // First line
todo(id: $id){ // Second line
name
date
}
}
`;
First Line:“$id”
here is a variable and it is a GraphQL “STRING” type (click Here to learn about all GraphQL types), the exclamation mark stands for ‘Non Null’
Second Line: We are then assigning the variable to the argument we would pass into our request.
Notice we only returned ‘name’ and ‘date’ from our query, excluding ’completed’. Graphql helps prevent over-fetching.
Now let’s use it in graphql-request.
Create a page in pages folder like so: ‘/pages/[id].js’, this allows us pass in our parameter in the request. If you are unfamiliar with this check out Docs .
export async function getServerSideProps({params }) { //Line 1
const variables = { // Line 2
id: params.id,
};
const res = await request(‘/api/graphiql’, TODO, variables); // Line 3
const data = res.todo;
return {
props: {
data
},
};
}
Line 1: we pass in ‘params’ for access to our url parameter
Line 2: we created a ‘variables’ object to pass in the expected ‘id’ variable in our request.
Line 3: we have a third parameter in our request where we pass in the variables.
Now we can display a single todo item in our page.
Full code:
const TODO = `
query todo($id:String!) { // First line
todo(id:$id) { // Second line
name
date
}
}
`
export async function getServerSideProps({params }) {//Line 1
const variables = { // Line 2
id: params.id
};
const res = await request(‘/api/graphiql’, TODO, variables); // Line 3
const data = res.todo;
return {
props: {
data
},
};
}
function TodoPage({data}){
return(
…
)
};
We will now be making a mutation. We do not need to use a data fetching method because we are not fetching data.
const ADD_TODO = `
mutation addTodo( //Line One
$name:String!
$date:String
$completed:Boolean!)
{
addPost(
name: $name
date:$date
completed:$completed)
{
name //Line Two
}
} `
Line One: notice the ‘mutation’ keyword
Line Two: we can also return data from a mutation
Using our mutation query in the component:
function Component () {
const[name, setName ] = React.useState("") //input state
function addTodo(e) { //submit function
e.preventDefault()
const variables = {
name, //from input state
date: new Date(),
completed: false
};
try{
const res = await request("api/graphql", ADD_TODO, variables);
console.log(res.data)
} catch(err) {
console.log(err.message)
}
}
return (
<div>
…
</div>
)
};
Done! I am glad you completed this. This is my first technical post, please excuse the mistakes or better still leave a comment.
Top comments (2)
Hi, can you help me pls with my code? I'd like to fetch data directly inside the component, not page. is it possible?
see here: reddit.com/r/learnjavascript/comme...
Good one 🙂