Axiosで速度改善のため、毎度APIを呼ばないようにする（〇〇秒キャッシュ）

# ページに遷移するたびにAPIを呼ぶのは効率が悪いため、ある程度の時間は再レンダリングしてもAPIを呼ばないようにする

独学の時はAPIを呼ぶのは基本一つしかなく、あまり速度が遅いとは感じませんでしたが、
本格的にアプリを作っていくと１ページに4種類のAPIを呼ばないといけないことになります。
その時に毎回全部のAPIを呼んでいると速度が遅くなる恐れがあります。
そこで、毎回呼ぶ必要のないAPIは次にAPIを呼ぶまでの時間を設定し、その間はレンダリングしてもAPIを呼ばないようにします。
# 実装していく
実際にコーディングしていきます。

## １、APIを呼ぶ設定

まずはAPIの呼び出し共通処理を記述します

```javascript
import axios from 'axios';

export const api = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/'
});

api.interceptors.response.use(
  response => {
      return response;
  },
  function (error) {
    switch (error.response.status) {
      case 400:
      case 401:
        console.log('認証エラーです');
      case 404:
        console.log('URL先がないです');
      default:
    }
  },
);

```
次に実際にAPIを呼び出す処理を実装します。
jsonplaceholderの「posts」と「users」の二つを呼び出しています。
そしてここでは検証用に毎秒レンダリングするように処理しています。（setInterval)
こうすることで、1秒経つ毎に毎回二つのAPIを呼び出しているようにしています

```javascript
import React, {useEffect, useState} from 'react';
import {StyleSheet, Text, FlatList, SafeAreaView} from 'react-native';
import {api} from '../api/api';

export const ApiResearch = () => {
  const [count, setCount] = useState(0);
  const [postsData, setPostsData] = useState([]);
  const [usersData, setUsersData] = useState([]);
  

  const getPostsData = async () => {
    const res = await api.get('posts');
    setPostsData(res.data);
  };

  const getUsersData = async () => {
    const res = await api.get('users');
    setUsersData(res.data);
  };

  useEffect(() => {
    getPostsData();
    getUsersData();
    const intervalId = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);
    return () => clearInterval(intervalId);
  },[count]);

  return (
    <SafeAreaView>
      <Text>{count}</Text>
      <Text style={styles.title} >ここからpostデータです</Text>
      <FlatList
        data={postsData}
        renderItem={({item}) => <Text>{item.title}</Text>}
        keyExtractor={item => item.id.toString()}
      />
      <Text style={styles.title}>ここからuserデータです</Text>
      <FlatList
        data={usersData}
        renderItem={({item}) => <Text>{item.name}</Text>}
        keyExtractor={item => item.id.toString()}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
    title: {
        fontSize:20,
        fontWeight:'bold',
        marginBottom:10
    }
   });

```
あとはこのApiResearce.jsをApp.jsで呼んでください。
では実際にReactNative Debbugerで確認してみましょう。
![スクリーンショット 2021-09-06 16.58.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/e9c040f2-999c-aa4c-d72f-ed5aef3fb755.png)
画像の通り、1秒毎にpostsとusersが呼び出されてるのがわかると思います。


## ２、axios cache adapterを使い、APIを呼ぶタイミングを設定する
必要なライブラリをインストール
```yarn add axios-cache-adapter```
APIの共通処理にcacheの設定をしていきます

```javascript
import axios from 'axios';
import {setupCache} from 'axios-cache-adapter';

const cache = setupCache({
  maxAge: 10 * 1000,
});


export const api = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/',
  adapter:cache.adapter
});

api.interceptors.response.use(
  response => {
      return response;
  },
  function (error) {
    switch (error.response.status) {
      case 400:
      case 401:
        console.log('認証エラーです');
      case 404:
        console.log('URL先がないです');
      default:
    }
  },
);
```
setupCacheをインポートし、キャッシュする時間を設定します。
今回は10秒経ったら再度取得するようにしたいので10*1000としています(ミリ秒なので*1000する必要があります)。
Debuggerで確認してみましょう
![スクリーンショット 2021-09-06 15.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/036460fb-29e4-a7fa-2c18-d4e473cb6a90.png)
今回は初期の一度のみ呼ばれているだけで、毎秒呼ばれてないですね。
![スクリーンショット 2021-09-06 15.55.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/15e6f778-c57b-7eb5-b108-0f51e262ce20.png)
10秒経ったので再度API通信がされました！

## ３、API毎にキャッシュする時間を設定する
最後にAPI毎に時間を設定していきます。
こうすることでリアルタイムにAPIを取得したいものと、何分、何時間に一回でいいもので分けることができます。
実装方法は簡単です。先程は共通処理に記述したので、APIを呼び出す処理の第二引数に加えるだけです。
先程の共通処理に記述したコードを削除し、ApiReseach.js（APIを呼び出しているところ）に追加で記述していきます

```javascript
import React, {useEffect, useState} from 'react';
import {StyleSheet, Text, FlatList, SafeAreaView} from 'react-native';
import {api} from '../api/api';
import {setupCache} from 'axios-cache-adapter';

const tenCache = setupCache({
  maxAge: 10 * 1000,
});

const thirtyCache = setupCache({
  maxAge: 30 * 1000,
});

export const ApiResearch = () => {
  const [count, setCount] = useState(0);
  const [postsData, setPostsData] = useState([]);
  const [usersData, setUsersData] = useState([]);
  

  const getPostsData = async () => {
    const res = await api.get('posts',{
      adapter:tenCache.adapter
    });
    setPostsData(res.data);
  };

  const getUsersData = async () => {
    const res = await api.get('users',{
      adapter:thirtyCache.adapter
    });
    setUsersData(res.data);
  };

  useEffect(() => {
    getPostsData();
    getUsersData();
    const intervalId = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);
    return () => clearInterval(intervalId);
  },[count]);

  return (
    <SafeAreaView>
      <Text>{count}</Text>
      <Text style={styles.title} >ここからpostデータです</Text>
      <FlatList
        data={postsData}
        renderItem={({item}) => <Text>{item.title}</Text>}
        keyExtractor={item => item.id.toString()}
      />
      <Text style={styles.title}>ここからuserデータです</Text>
      <FlatList
        data={usersData}
        renderItem={({item}) => <Text>{item.name}</Text>}
        keyExtractor={item => item.id.toString()}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
    title: {
        fontSize:20,
        fontWeight:'bold',
        marginBottom:10
    }
   });

```

10秒毎に呼び出すAPIと30秒毎に呼び出すAPIで分けています。
では実際にDebuggerで確認してみましょう
![スクリーンショット 2021-09-06 16.44.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/c3017eab-be5e-dc43-a428-2613169708be.png)

画像の通りusersの方はpostsが3回呼ばれると1回呼ばれているのがわかると思います。
10秒、20秒のタイミングではusersは呼ばれていません！

エンジニア初学者でエンジニア転職を目指されている方はここまで実装する必要はないかもしれないですが、
転職用のポートフォリオを作る際にこのようにAPI毎にキャッシュ時間を設定して速度改善をしていると他の人のポートフォリオと差別化が図れますし、かなりポイントが高いと思います:thumbsup_tone2:
自分も初めて実装しましたが、想像以上に簡単だったので使ってみてください！！