Twitter APIを使ってNuxt.jsで検索、表示するアプリをサクッと作ってみよう

## はじめに
TwitterAPIとNuxt.jsの動作確認を目的としたハンズオン的なアプリの作成になります。
現在は検索だけなら英語文章による審査はいらないようなので、サクッと作ってしまいましょう！

## Twitter APIキーを取得する
<a href="https://developer.twitter.com/en/apps/">TwitterDevelopersサイト</a>
登録されていない方は上記サイトからAPI利用申請を行ってください。
申請にはTwitterアカウントが必要になります。
Bearer Tokenをメモしておいてください。

## Nuxt.jsを動かしてみる

Node環境が無い場合は先にNodeをインストールしてください。
下記のコマンドでNuxtプロジェクトが作成できます。

```bash
npm init nuxt-app twitter-text-searcher
```

こんな感じで答えてあげてください

```bash
? Project name: twitter-text-searcher
? Programming language: TypeScript
? Package manager: Npm
? UI framework: Vuetify.js
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Single Page App
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username?
? Version control system: Git
```

できあがったプロジェクトに移動して、試しに起動してみましょう。

```bash
cd twitter-text-searcher
npm run dev
```

http://localhost:3000/
にアクセスするとこんな感じになってると思います。

 ![スクリーンショット 2022-06-13 22.47.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708801/09849eb3-1cad-78f5-57ca-a8d1ca883d6c.png)

## Twitter APIを使ってみよう
まずこのアプリのファイル構成の完成形を示しておきます。
```bash
.
├── api
│   ├── index.ts
│   └── twitter
│       └── twitter_api.ts
├── assets
│   └── variables.scss
├── components
├── layouts
│   ├── default.vue
│   └── error.vue
├── node_modules
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
│   ├── TweetList.vue
│   ├── index.vue
│   └── inspire.vue
├── static
├── store
└── tsconfig.json
```

最初にNuxt.jsでTwitterAPIを叩いて返ってきた情報をJSONで返すだけのAPIを作ってみます。
expressとtwitter-api-v２をインストールします。

```bash
npm install --save express
npm install --save twitter-api-v2
```

ルートにapiディレクトリを作成します。
```bash
mkdir api
```

nuxt.config.jsを編集します
```javascript:nuxt.config.js
  ~ 省略 ~
  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
  },

  // 追加
  serverMiddleware: ['~/api']
}
```

apiディレクトリ内にindex.ts、twitterディレクトリを作成し、中にtwitter_api.tsを作成
```bash
touch api/index.ts
mkdir api/twitter
touch api/twitter/twitter_api.ts
```

twitter_api.tsを編集します。
※二行目にBearer Token直接入れていますが、普通はAPI Keyは直接書きません(今回は動作確認が目的なので直接書いてます)。
GitHub等にコードをあげる際はBearer Tokenを入れたまま上げないように注意してください！
```javascript:twitter_api.ts
import { TwitterApi } from 'twitter-api-v2';
const client = new TwitterApi("取得したBearer Tokenを入れる");
let query: string | undefined = undefined
let nextToken: string | undefined = undefined

export const searchTweet = async (searchText: string) => {
  const result = await client.v2.search(searchText, {max_results: 10})
  query = searchText
  nextToken = result.data.meta.next_token
  return result.data.data
}

export const searchNext = async () => {
  if (!nextToken || !query) return
  const result = await client.v2.search(query, {next_token: nextToken})
  nextToken = result.data.meta.next_token
  return result.data.data
}
```

index.tsを編集します。
```javascript:index.ts
import express from 'express'
const app: express.Express = express()
import { searchTweet, searchNext } from "./twitter/twitter-api";

app.get('/searchTweet', async (req: express.Request, res: express.Response) => {
  const query = req.query['searchText'] as string

  const result = await searchTweet(query)

  res.json(result)
})

app.get('/searchNext', async (req: express.Request, res: express.Response) => {
  const result = await searchNext()

  res.json(result)
})

module.exports = {
  path: '/api',
  handler: app
}

```

ここで一度動作確認をしてみましょう
```bash
npm run dev
```

立ち上がったら下記のURLにアクセスしてみて
http://localhost:3000/api/searchTweet?searchText=nuxt
ブラウザにJSONデータが表示されたら成功です

## 画面を作る
データの取得に成功したので、次はvueで画面を書いていきましょう

UIフレームワークは使いやすいvuetifyを採用しましたが、レイアウトはシンプルな方がいいのでデフォルトのテーマは外します。

layoutディレクトリ内のdafault.vueを編集します
```vuejs:index.ts
<template>
  <div style="margin: 10px">
    <Nuxt />
  </div>
</template>

<script>
export default {
  name: 'DefaultLayout',
  data () {}
}
</script>
```

Vueファイルを作成します
```bash
touch pages/TweetList.vue
```

Vueファイルを編集します

```vuejs:TweetList.vue
<template>
  <div>
    <v-row justify="center" align="center">
      <v-col cols="12" style="position: fixed; background-color: white; z-index: 3;">
        <v-text-field v-model="searchText" @change="search" label="検索ワード" hide-details></v-text-field>
      </v-col>
      <v-col cols="4" style="margin-top: 70px">
        <v-btn @click="next" style="margin-left: 10px">次へ</v-btn>
      </v-col>
      <v-col cols="12">
        <v-data-table
          hide-default-footer
          :headers="headers"
          :items="response"
          :items-per-page="-1"
          class="elevation-1"
        ></v-data-table>
      </v-col>
      <v-col cols="4">
        <v-btn @click="next" style="margin-left: 10px">次へ</v-btn>
      </v-col>
    </v-row>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      searchText: '',
      response: [],
      headers: [
        { text: 'テキスト', value: 'text' },
      ],
    }
  },
  methods: {
    // 検索
    search() {
      axios
        .get(`/api/searchTweet?searchText=${this.searchText}`)
        .then(response => {
          this.response = response.data
        })
        .catch(error => {
          console.log(error)
        })
    },
    // 次へ
    next() {
      axios
        .get(`/api/searchNext`)
        .then(response => {
          this.response = this.response.concat(response.data)
        })
        .catch(error => {
          console.log(error)
        })
    }
  },
}
</script>
```

http://localhost:3000/TweetList
にアクセスして、検索してみてください(参考のgifではモックデータを表示させています)

![テスト操作.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708801/46ebdbf3-cf2d-32b4-565b-86cf121ebecb.gif)

## おわりに
お疲れ様です。これで今回のアプリは終了です。
私がNuxt.jsを触ってみたい、せっかくなら前から気になっていたTwitter APIを使ってみたいということで今回のアプリを作ってみた次第です。
次へボタンを押さずに本家twitterのようにスクロールで自動的に読み込むようにできればかっこいいですね！
もしNuxt.jsの使い方等で間違っている部分があればご指摘いただけますと幸いです。