---
title: Getting Started
---

## Our first query

Let's create our first query with `graphql-ppx`. In this case we will write a
query to fetch the current user. We can create a query with the following code.

```reason
[%graphql {|
  query UserQuery {
    user {
      id
      name
    }
  }
|}];
```

This is quite similar to how we could define a query in JavaScript. Depending on
the client, in JavaScript we usually do something like this:

```js
let query = gql`
  query UserQuery {
    user {
      id
      name
    }
  }
`;
```

However, the ReasonML code does much more. It will not only create a query that
you can pass to the client. It will also generate the types of the data that we
get back from the GraphQL server.

The shape of the data that we get back from the server has the type
`UserQuery.Raw.t`. This represents the data exactly like the response type. The
type that is being generated by `graphql-ppx` is:

```reason
module Raw = {
  type t_user = {
    id: string,
    name: Js.Nullable.t(string)
  };
  type t = {
    user: t_user
  };
}
```

So once we successfully get data back from the server it is of type `Js.Json.t`.
To work with it we can typecast it into `UserQuery.Raw.t`.

```reason
let typedData = UserQuery.unsafe_fromJson(data)
```

`UserQuery.unsafe_fromJson` is a helper function that will cast a Js.Json.t to
the GraphQL `Raw` type. In JavaScript this will not generate any code, it will
just tell the compiler to cast it into the `Raw` type. With GraphQL we know that
if we get a response that this conforms to the shape of our query. This allows
us to convert the generic `Js.Json.t` to richer and more specific type. To get
the user's id, we can get it like we are used to in ReasonML:

```reason
let userName = typedData.user.id
```

As it is a normal ReasonML value now, we can do everything we want with it, like
for instance pattern matching.

```reason
let userName = switch(user) {
  | {user: {id}} => id
}
```

## Parsing data

However it's not perfect. In this example it would be nice if the user's name
could be converted to a more idiomatic ReasonML data structure like an `option`
type. This is exactly what parse does.

```reason
let parsedData = UserQuery.parse(typedData)
```

With parse the data is converted into idiomatic ReasonML data types. In this
case the name is converted from `Js.Nullable.t(string)` to simply
`option(string)`. This means we can write the following code:

```reason
let name = switch(parsedData) {
  | {user: {name: Some(name)}} => name
  /* the user's name is null */
  | _ => "Anonymous"
}
```

Also in some cases the JSON data can not be directly represented by a ReasonML
type. For instance in case of a union, ReasonML doesn't allow arrays to contain
values with different types, so it cannot be directly mapped. In those cases the
raw type will be an _opaque_ type[^1]. When the raw result is parsed it is
converted to a list of a variant.

Usually you will not be working with the raw type. This is an implementation
detail that is normally only used inside of the GraphQL client. In most cases
the parsed result will be what you get back from the library.

## Fragments

## Using a client

[^1]:

An opaque type is essentially a value that you can't access directly. So the
value is _opaque_ to the user
