Medium like Blog Post Builder in React with graphql using typescript
Tags: typescript, graphql, hooks, react
Published: 2021-04-10 07:23:16

This blog post is about will give you complete knowledge about how to start with react Graphql using typescript and the separation of concern and clean architecture folder structure.
 

Keep in mind that if you get stuck on any step, refer to the [Github repo](https://github.com/selvaece25/Medium-like-Blog-Post-Builder-in-React-using-typescript)

To find the completed project, [Demo link] (https://citye.csb.app/#/)

### This is what we are going to create:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/knfgr3by8bvsriv226u1.gif)

###What is GraphQL?
Before going forward, let me give a very brief overview of GraphQL and what all things we are going to discuss. So GraphQL is a query language for APIs that is developed by Facebook. It is an efficient alternative to REST because of its features such as:

* With GraphQL there's no over fetching or under fetching of data, unlike REST.
* Strongly typed graphQL schema which can be written in GraphQL Schema Definition Language (SDL) helps you validate your API requests during its compile time.
* With the development of various GraphQL libraries (Apollo, Relay, etc) you are getting a lot of features such as caching, realtime data, etc.
* It provides a large and amazing community! You can always get your queries answered whenever stuck.

This was just a basic introduction to GraphQL, but I recommend you to visit the site to gain deeper insights of the same.

#### What we'll do?

I will be mainly focussing on the front-end side, where I am gonna explain the two very useful react hooks **useQuery** and **useMutation**, how are we using these in our project for GraphQL operations along with the code.

#### Wait...what are GraphQL operations?

GraphQL provides various types of operations such as Query, Mutation, and Subscription which act as the entry points for the requests sent by the client. In this blog, I'll be discussing the first two types i.e. Query and Mutation.

I'm going to use [graphql-hooks](https://www.npmjs.com/package/graphql-hooks) have two operations useQuery, useMutation

##### UseQuery: Basic syntax:

```javascript
const { loading, error, data } = useQuery<Type1, Type2>(
    QUERY_STRING,
    { variables: <variable>,
onCompleted:()=>{console.log("query successful",data);}
,
onError:(error)=>{console.error(error);},
});

```
data : The required data we are getting after the query is successful.
loading : It is a boolean value, if true, it means the query is still in flight. After it is successful the value of loading changes to false.
error : It stores the error if occurred while querying.

##### useMutation: Basic syntax:

```javascript
 const [mutateFunction,{ error,loading}] = useMutation<Type>(MUTATION_STRING, {
    onCompleted: () => {
    console.log("details updated")
    },
    onError: (error) => {
    onError:(error)=>console.error(error);
    },
    refetchQueries: [{ query: QUERY_STRING, variables: <variable>],
  });

```
mutateFunction : It is the mutate function which can be called anytime to run the mutation.
The second parameter is the object representing the mutation's execution status such as error , loading which have been explained above.

To use those operation in App need to wrap your app with the provider:

```javascript 
import { GraphQLClient, ClientContext } from 'graphql-hooks'

const client = new GraphQLClient({
  url: '/graphql'
})

function App() {
  return (
    <ClientContext.Provider value={client}>
      {/* children */}
    </ClientContext.Provider>
  )
}
```

Now in your child components you can make use of useQuery
```javascript

import { useQuery } from 'graphql-hooks'

const HOMEPAGE_QUERY = `query HomePage($limit: Int) {
  users(limit: $limit) {
    id
    name
  }
}`

function MyComponent() {
  const { loading, error, data } = useQuery(HOMEPAGE_QUERY, {
    variables: {
      limit: 10
    }
  })

  if (loading) return 'Loading...'
  if (error) return 'Something Bad Happened'

  return (
    <ul>
      {data.users.map(({ id, name }) => (
        <li key={id}>{name}</li>
      ))}
    </ul>
  )
}

```
More details and options you can refer [link](https://www.npmjs.com/package/graphql-hooks)


### Our project's structure:

Before we begin let's talk about how our project is going to be organized.
 
Once we create our React app using create-react-app, we will have our base React app. Once inside that application, we will create a component pattern and Our folder structure will look like the following:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4f6cg3y00sui3bo6aqqg.png)


Now, let’s go over the folders one by one and the and understand the motivation behind them and the type of files you would store in them:

src/ - Contains all of our react codebase.
    graphql - queries: This folder contains all static graphql query with props settings
    pages - The name is pretty self-explanatory. It contains all the Stateful Components as discussed above.
    views - This folder contains all the Presentational/Stateless Components as discussed above.
    routes - This folder contains public, private, session differentiation and mainly for App navigation 
    start - Base react component.
    types - Typescript related files or functions.
    utils - Helper functions
    use -  custom hooks
    templates - I create a different template for React with React Router 4 like global, error handling, promotions like so on.


 Hopefully you understood how to setup a clean, efficient and maintainable folder structure for your React Apps.

### Our goal today is to:

1. Create a new React Blogger App
2. Have [Graphqlzero almansi Api](https://graphqlzero.almansi.me/api)
3. Using React Routing, be able to navigate our app

#### Generate project with CreateReactApp:
I often (to not say always 😁) use Create React App to initiate my React projects.

In order to generate our project run :
```javascript
npx create-react-app my-app --template typescript
```

let's start coding. 


#### Setting up React Router:

To get React Router going, we are going to need to install our dependency. In the project, run the following command:
```javascript
npm install --save react-router-dom
```

It define the route and call the Auth.

```javascript
// src/start/Routes.tsx

routesTemplates.map((routesTemplate) => {
  const { routes: appRoutes, template: Template , type} = routesTemplate;
  return appRoutes.map( (appRoute) => {
    return (
      <Route
        exact={appRoute.exact}
        path={appRoute.path}
        key={appRoute.path}
        render={(route) =>
          <Auth
            appRoute={appRoute}
            Template={Template}
            route={route}
            type={type}
          />
        }
      />
    );
  });
})
```

#### Route Types

There are three route types defined in the project.
```javascript
// src/routes/routeTypes.tsx

export enum routeTypes {
  private = 'private',
  public = 'public',
  session= 'session',
}
```
private: private pages like profile, edit-profile, etc. If the user isn’t logged then must to show the login page.
public: public pages like about-us, contact, etc.
session: session pages like login and sign-up. If the user is logged then must to redirect to the private dashboard.

#### Routes Template
In this file you can define the routes, the template and the rights (public, private, session).

```javascript
// src/routes/index.tsx

const routesTemplate: IRouteTemplate[] = [
  {
    routes: privateRoutes,
    template: GlobalLayout,
    type: routeTypes.private,
  },
  ...
];
```

#### Auth

Verify the rights and redirection.
```javascript
// src/start/Auth.tsx

if (isPrivate(type) && !global.logged) {
  return <GlobalLayout Component={Error403} route={route} />;
}

if (isSession(type) && global.logged) {
  return <Redirect to="/" />
}

const Layout = appRoute.template ? appRoute.template : Template;
return <Layout
  Component={appRoute.component}
  route={route}
/>;
```
### Building our React components
In this application, we are going to have fives pages for templates:

* All Posts List with Author Details
* All Author List with Posts listing
* Post details 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oisxl9vkx1ruyevrsbrw.png)


#### Putting it all together
Now that we have our components set up, we can head on over to “localhost:3000” and see all pages get render.

Feel free to ask questions in any area you don't understand.

To be continued on next article about Graphql implementation...