Creating a Reddit Clone Using React and GraphQL - 15
Tags: react, typescript, graphql, redditclone
Published: 2021-03-27 18:11:21

### This blog post originally posted on my blog site and you can find it [here](https://www.rasikag.com/posts/creating-a-reddit-clone-using-react-and-graphql-15).


From this blog post, we are going to set up the pagination. So we need to seed a lot of data into the database. We can create mock data using [mockaroo](https://mockaroo.com/) site and export those data as the SQL query.

Then run the create migration command to generate the migration file in the server application.

```javascript

npx typeorm migration:create -n FakePost

```

Inside that migration file, you will see 2 methods called `up` and `down` . Add this code line to `up` method.

```javascript
await queryRunner.query(`
... mockaroo queries goes here `);
```

Then change the server index file to run this migration file. You can move that file into `migration` folder. Add the migration property to `createConnection` method.

```javascript

migrations: [path.join(__dirname, "./migrations/*")],

```

Then below that method add this line of code to run the migration.

```javascript
await conn.runMigrations();
```

At this point, we are not returning the text of the post. But we don’t want to show the full text on the home page, on the home page we can only show a limited number of characters.

We can Resolver annotation to `@Resolver(Post)` and we are adding FiledResolver.

```javascript

@FieldResolver(() => String)
textSnippet(@Root() root: Post) {
  return root.text.slice(0, 50);
}

```

Also, we are using `cursorPagination` method that taking last post timestamp and return the older posts. We can change the `posts` method to user query builder and return result as the number of limit. Here we are taking 2 parameters as `limit` and `cursor`.

```javascript

async posts(
@Arg("limit", () => Int) limit: number,
@Arg("cursor", () => String, { nullable: true }) cursor: string | null
): Promise<Post[]> {
  // previously we took all the posts

  // return await Post.find();
  // using query builder
  const realLimit = Math.min(50, limit);
  const qb = getConnection()
  .getRepository(Post)
  .createQueryBuilder("p")
  .orderBy('"createdAt"', "DESC")
  .take(realLimit);

  if (cursor) {
  // take the old post using cursor
  qb.where('"createdAt" < :cursor', {
  cursor: new Date(parseInt(cursor)),
  });
  }
  return qb.getMany();

}


```

Now our back-end code is completed. Now we need to change front-end `graphql` query to match with these 2 parameters.

```javascript

query Posts($limit: Int!, $cursor: String) {
  posts(cursor: $cursor, limit: $limit) {
    id
    createdAt
    updatedAt
    title
    textSnippet
  }
}

```

After changing this `graphql` query, execute the `yarn gen `command. It will update the generated methods to retrieve the posts.

Now we can change the outlook of the post by adding some `chakra-ui` components.

We can add a header and re-arrange the Create Post link.

```javascript
<Flex align="center">
  <Heading>Reddit Clone</Heading>
  <NextLink href="/create-post">
    <Link ml="auto">Create Post</Link>
  </NextLink>
</Flex>
```

There are a few scenarios that we need to handle. One is if there is no data and still fetching, we need to show the below message.

```javascript
if (!fetching && !data) {
  return <div>there is some error in graphql query</div>;
}
```

To use `fetching` we need to assign it from `graphql` query.

```javascript

const [{ data, fetching }] = usePostsQuery({
  // ... rest of the code

```

We can update the `post` UI as below to show post with its post snippet.

```javascript

<Stack spacing={8}>
{data!.posts.map((p) => {
return (
  <Box key={p.id} p={5} shadow="md" borderWidth="1px">
    <Heading fontSize="xl">{p.title}</Heading>
    <Text mt={4}>{p.textSnippet} </Text>
  </Box>
);
})}
</Stack> 

```

Then if there is data we can show a button to load more post. Above ending `</Layout>` tag add below code.

```javascript

{data ? (
<Flex>
  <Button onClick={() => { }); } m="auto" my={8} isLoading={fetching} >
    load more
  </Button>
</Flex>
) : null}

```

Now we are adding the pagination resolver from cache to `createUrqlClient` . This is the function that append the post in the cache to the new posts.

```javascript

const cursorPagination = (): Resolver => {
  return (_parent, fieldArgs, cache, info) => {
    const { parentKey: entityKey, fieldName } = info;
    const allFields = cache.inspectFields(entityKey);
    console.log("allFields: ", allFields);
    const fieldInfos = allFields.filter((info) => info.fieldName === fieldName);
    const size = fieldInfos.length;
    if (size === 0) {
      return undefined;
    }

    const fieldKey = `${fieldName}(${stringifyVariables(fieldArgs)})`;

    const isItInTheCache = cache.resolve(entityKey, fieldKey);
    info.partial = !isItInTheCache;
    const results: string[] = [];
    fieldInfos.forEach((fi) => {
      const data = cache.resolve(entityKey, fi.fieldKey) as string[];
      console.log(data)
      results.push(...data);
    });

    return results;

  };
};

```

We need to set this in to exchange as `cacheExchange` .

```javascript

resolvers: {
  Query: {
    posts: cursorPagination(),
  },
},

```

Now we can add the `onClick` functionality. We can use the state to set the cursor. First, create the initial statue for the `cursor`.

```javascript

const [variables, setVariables] = useState({
  limit: 10,
  cursor: null as null | string,
});

```

Then once we click the button change the cursor to last post’s timestamp. This way we can load the new posts.

```javascript

<Button
  onClick={() => {

  setVariables({
  limit: variables.limit,
  cursor: data.posts[data.posts.length - 1].createdAt,
  });
  }}
  m="auto"
  my={8}
  isLoading={fetching}
>
// ...rest of the code

```

Now we can see it will update the new posts in the view.

---

Thanks for reading this. 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.

**References:**

This article series based on the [Ben Award - Fullstack React GraphQL TypeScript Tutorial](https://www.youtube.com/watch?v=I6ypD7qv3Z8). This is amazing tutorial and I highly recommend you to check that out.

Main image [credit](https://www.pexels.com/photo/picturesque-view-of-lake-and-forest-in-mountains-3934023/)