All Articles

Creating a Reddit Clone Using React and GraphQL - 02

inner peace

This is a series of posts and the previous one you can find from here.

Learning React with Ben Awad — 01

Note:

use yarn watch to build the JavaScript files.

use yarn devto run with nodemon .

All these commands set up on package.json file.

At this point from the previous post, we set up our databases. That means we can successfully add data to the database. But here, we are using GraphQL . So, let’s set up the QraphQL to our project. Also, we are right now building the backend web service. Let’s add relevant packages. Use below command to add express web framework, GraphQL support to express server by apollo-server-express and GraphQL by graphql and TypeScript support for creating Schemas by type-graphql

yarn add express apollo-server-express graphql type-graphql

Then add reflect-metadata. This is the metadata reflection API that supports to add attributes or annotations and more. Use below command to add it.

yarn add reflect-metadata

Also, we need to add express TypeScript support. Using below command let’s add it.

yarn add -D @types/express

Now we created a server and it is up right now.

But here we are using GraphQL. So we create an ApolloServer object and pass the express server into the middleware pipeline. You can check that we need to add the config object that telling what are the resolvers .

const apolloServer = new ApolloServer({
  schema: await buildSchema({
    resolvers: [HelloResolver, PostResolver],
    validate: false,
  }),
  context: () => ({ em: orm.em }),
});
apolloServer.applyMiddleware({ app });

These resolvers are query handlers for the GraphQL. In here we can define our query functions and mutation functions. To define a class as resolver use @Resolver annotation.

@Query annotation. 

Define as this is a query. Pass the return type as the first parameter. If you want to return null, you need to explicitly define it.

@Query(() => Post, { nullable: true })

Once you run the webserver you can open graphql the playground by localhost:[port]/graphql

But the thing is Post is an Entity. We can convert it to GraphQL object. use @ObjectType() and @Field() annotations. (check the below link )

rasikag/reddit-clone

Now we need to database context. We can create it and pass it as @resolver function parameter. Here we are creating the context object.

export type  RedditDbContext {
  em: EntityManager<any> & EntityManager<IDatabaseDriver<Connection>>
}

Then user this context in post resolver as a parameter in query or mutation function.

One thing is there is GraphQL type and Entity type. Kinda duplication. Also, make the return type as Promise<Post[]> to avoid the returning any type.

  @Mutation(() => Post) // GraphQL return type that map to same Post Entity
  async createPost(
  @Arg("title") title: string,
  @Ctx() { em }: RedditDbContext
  ): Promise<Post> // same Entity return type
  {
  ...
  }

Now all set and if you run this you will get an error because GraphQL yield to set the type in createdAt property in Post entity.

NoExplicitTypeError: Unable to infer GraphQL type from TypeScript reflection system. You need to provide explicit type for 'createdAt' of 'Post' class.

To resolve that add types explicitly for the Post entity for support GhraphQL.

@Field(() => String) // explicitly define type.
@Property({ type: "date" })
createdAt = new Date();

Query or Mutation method needs 2 parameters. Context object and Arguments.

Now we set up all the things and you can go GraphQL playground and execute the below query to get all posts from the database.

{
  posts {
    id,
    createdAt,
    updatedAt,
    title
  }
}

Hola… We got the data from GraphQL

Now we are going to create all the CRUD operations for the Post entity. These methods should return a Promise. Once we implement all the CRUD methods we can execute below GraphQL queries.

To get post by post id execute below query.

{
  post(id:3){
    title
  }
}

We can create a new post using the below query. It is a mutation query. Also, make attention that how we pass the parameters.

mutation {
  createPost(title:"Hello from GraphQL"){
    title,
    id
  }
}

Here is the update post query.

mutation {
  updatePost(id:1, title: "I am going to update this title") {
    title
  }
}
// the title is what are the values that we need as return values

Here is the delete post GraphQL query.

mutation{
  deletePost(id:1)
}

Once you closely pay the attention to the console , you will see the query executed by GraphQL.

All the code related to this post, you can find in here.

rasikag/reddit-clone

I will wrap-up this note from here. Soon I will publish next part of this note.

If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.

That’s for today friends. See you soon. Thank you

Main image credit