ページに遷移するたびにAPIを呼ぶのは効率が悪いため、ある程度の時間は再レンダリングしてもAPIを呼ばないようにする
独学の時はAPIを呼ぶのは基本一つしかなく、あまり速度が遅いとは感じませんでしたが、
本格的にアプリを作っていくと1ページに4種類のAPIを呼ばないといけないことになります。
その時に毎回全部のAPIを呼んでいると速度が遅くなる恐れがあります。
そこで、毎回呼ぶ必要のないAPIは次にAPIを呼ぶまでの時間を設定し、その間はレンダリングしてもAPIを呼ばないようにします。
実装していく
実際にコーディングしていきます。
1、APIを呼ぶ設定
まずはAPIの呼び出し共通処理を記述します
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を呼び出しているようにしています
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で確認してみましょう。
画像の通り、1秒毎にpostsとusersが呼び出されてるのがわかると思います。
2、axios cache adapterを使い、APIを呼ぶタイミングを設定する
必要なライブラリをインストール
yarn add axios-cache-adapter
APIの共通処理にcacheの設定をしていきます
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秒経ったら再度取得するようにしたいので101000としています(ミリ秒なので1000する必要があります)。
Debuggerで確認してみましょう
今回は初期の一度のみ呼ばれているだけで、毎秒呼ばれてないですね。
10秒経ったので再度API通信がされました!
3、API毎にキャッシュする時間を設定する
最後にAPI毎に時間を設定していきます。
こうすることでリアルタイムにAPIを取得したいものと、何分、何時間に一回でいいもので分けることができます。
実装方法は簡単です。先程は共通処理に記述したので、APIを呼び出す処理の第二引数に加えるだけです。
先程の共通処理に記述したコードを削除し、ApiReseach.js(APIを呼び出しているところ)に追加で記述していきます
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で確認してみましょう
画像の通りusersの方はpostsが3回呼ばれると1回呼ばれているのがわかると思います。
10秒、20秒のタイミングではusersは呼ばれていません!
エンジニア初学者でエンジニア転職を目指されている方はここまで実装する必要はないかもしれないですが、
転職用のポートフォリオを作る際にこのようにAPI毎にキャッシュ時間を設定して速度改善をしていると他の人のポートフォリオと差別化が図れますし、かなりポイントが高いと思います
自分も初めて実装しましたが、想像以上に簡単だったので使ってみてください!!