Using faker.js on Next.js API route
Tags: api, vercel
Published: 2021-04-04 14:54:56

[Next.js](https://nextjs.org/) provides a neat functionality to [create API routes](https://nextjs.org/docs/api-routes/introduction). Any file inside `pages/api` will be treated as an API endpoint instead of a `page`.

So let's create an API endpoint with dynamic [faker.js](https://github.com/marak/Faker.js/) data.

First, we need to initialize a Next.js app - `yarn create next-app faker-js-on-next-js-api-route` command is here to rescue! And because I prefer a type safety and I like TypeScript, we will initialize it as well.

With `touch tsconfig.json` (file will be populated after running `yarn run dev` command), we will create a config file for TypeScript. With `yarn add --dev typescript @types/react`, we will install all the dependency that we will need.

The next thing that we need to do is rename every file extension from `.js` to `.tsx`. After renaming, we can stage our files and commit them.

```bash
git add -A && git commit -m "initialize typescript"
```

Our project has styles that we will not need for this kind of project, so I will remove the `styles` folder and Remove `.css` imports from `pages/_app.tsx` and `pages/index.tsx` files. Also, I have removed all the unnecessary code from the `pages/index.tsx` file, so it looks like this:

```tsx
// pages/index.tsx

export default function Home() {
  return (
    <div>
      <h1>Hello, Vercel!</h1>
    </div>
  )
}
```

To keep our changes more granular I'm committing here as well

```bash
git add -A && git commit -m "remove styles"
```

Next, we will rename `pages/api/hello.tsx` to `pages/api/customers.tsx` and we will install faker.js dependecy with `yarn add faker` and type definitions with `yarn add @types/faker -D`

Now, let's edit our `customers.tsx` file. We need to import a faker instance and then default export our function, which accepts `req` (An instance of http.IncomingMessage) and `res`(An instance of http.ServerResponse) parameters. Both `req` and `res` have some helper functions and middlewares on top of the HTTP classes.

To generate customers, we need to create an empty new array. To the `arrayLength` parameter, we will pass `10` (We will make this dynamic later on). Then we need to spread the newly created array to an empty array to make it iterable. Then we are going to `map` through this array. We will omit the `value` parameter by passing the `_`, and we will use the `index` to see the current index of the object. We will return an object which will look like this:

```ts
const customer = {
  index,
  name: faker.name.findName(), // generate the fake name
  city: faker.address.city(), // generate the fake city
}
```

Last but not least, we need to set the response status to `200` (OK) and then return a JSON response with our customer's data (we need to stringify customers object with the `JSON.stringify()` method).

```ts
// pages/api/customers.tsx

import faker from 'faker'

export default (req, res) => {
  const customers = [...new Array(10)].map((_, index) => {
    return {
      index,
      name: faker.name.findName(),
      city: faker.address.city(),
    }
  })

  res.status(200).json(JSON.stringify(customers))
}
```

If we go to [http://localhost:3000/api/customers](http://localhost:3000/api/customers) (If you are using a different port replace this URL), we will see that we get the data.

Now let's make the data more dynamic, at least the length. Instead of hardcoded `arrayLength`, we will receive a `limit` from the request body (if `limit` won't be provided, we will use fallback value, e.g. `10`).

First, we need to define a limit constant and check if it was provided in the body. If not, we will use `10`.

```tsx
const limit = JSON.parse(req.body)?.limit ?? 10
```

Then we can safely replace `[...new Array(10)]` with `[...new Array(limit)]`

After this refactoring, you can test it with [Postman](https://www.postman.com/), [Insomnia](https://insomnia.rest/), or your other favorite tool, or you can stay with me for a little bit longer and test it within the app.

Inside the `pages/index.tsx` file, We will create a state for our data. We will use the `useEffect` hook that will be run only on the initial mount (empty dependency array). Within `useEffect` we will create an async `fetchData` function that will fetch our `/api/customers` api endpoint. We will pass a stringified object with our `limit` key to the body of the' fetch' function options. Then we will return a JSON representation of the response. Next, we will call the `fetchData` function, and in the `then` method we will set the state with incoming data.

I'm not handling errors here for simplicity, and I'm assuming that if there is no data in the state, the state should be loading.

```tsx
// pages/index.tsx

import { useEffect, useState } from 'react'

export default function Home() {
  const [data, setData] = useState(null)

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('/api/customers', {
        method: 'POST',
        body: JSON.stringify({
          limit: 100,
        }),
      })

      return response.json()
    }

    fetchData().then((data) => {
      setData(data)
    })
  }, [])

  return (
    <div>
      <h1>Hello, Vercel!</h1>
      {!data ? '...loading' : <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  )
}
```

And that's it! Pretty simple right? Hopefully, you find this article, and feel free to contact me if you have any questions or feedback!

See you next time!