前回の記事の続きです。
まずはバーコードスキャナーの部分のUIを構築します。
バーコードスキャナーの部分のUIを構築する
import React, { useState, useEffect } from "react"; import { Text, StyleSheet, Button, SafeAreaView } from "react-native"; import { BarCodeScanner } from "expo-barcode-scanner"; export default function App() { const [hasPermission, setHasPermission] = useState(null); const [scanned, setScanned] = useState(false); useEffect(() => { (async () => { const { status } = await BarCodeScanner.requestPermissionsAsync(); setHasPermission(status === "granted"); })(); }, []); const handleBarCodeScanned = ({ type, data }) => { setScanned(true); alert(`Bar code with type ${type} and data ${data} has been scanned!`); }; if (hasPermission === null) { return <Text>Requesting for camera permission</Text>; } if (hasPermission === false) { return <Text>No access to camera</Text>; } const styles = StyleSheet.create({ barcode: { width: "100%", height: "40%" }, container: { flex: 1 } }); return ( <SafeAreaView style={styles.container}> <BarCodeScanner onBarCodeScanned={scanned ? undefined : handleBarCodeScanned} style={styles.barcode} ></BarCodeScanner> {scanned && ( <Button title={"Tap to Scan Again"} onPress={() => setScanned(false)} /> )} </SafeAreaView> ); }
上のようになればOKです。
今回は楽天APIを使用していきます。
APIを使うためaxios
というライブラリを使用します。
% yarn add axios
axiosがpackage.json
に追加されたことを確認したら、次に本の情報をaxios
で取得する処理を実装していきます。
App
ファンクションコンポーネントに追記していきます。
const [bookInfo, setBookInfo] = useState(null); const fetchBooks = async URL => { try { const response = await axios.get(URL); //本の情報を取得する setBookInfo(response.data.Items[0].Item); } catch (error) { alert("エラーが発生しました"); } };
次にhandleBarCodeScanned
ファンクションを修正します。
const handleBarCodeScanned = ({ type, data }) => { setScanned(true); const URL = `https://app.rakuten.co.jp/services/api/BooksTotal/Search/20170404?format=json&isbnjan=${data}&applicationId=${○○○○}`; fetchBooks(URL); };
applicationIdは楽天APIの利用登録したとき与えられるIdです。
本を再検索するときはstate
の値たちをもとに戻します。
const resetSession = () => { setScanned(false); setBookInfo(null); };
本の情報を出力させるUIを追加した完成したコードが以下のようになります。
import React, { useState, useEffect } from "react"; import { Text, StyleSheet, Button, SafeAreaView, Image } from "react-native"; import { BarCodeScanner } from "expo-barcode-scanner"; import axios from "axios"; export default function App() { const [hasPermission, setHasPermission] = useState(null); const [scanned, setScanned] = useState(false); const [bookInfo, setBookInfo] = useState(null); useEffect(() => { (async () => { const { status } = await BarCodeScanner.requestPermissionsAsync(); setHasPermission(status === "granted"); })(); }, []); const handleBarCodeScanned = ({ type, data }) => { setScanned(true); const URL = `https://app.rakuten.co.jp/services/api/BooksTotal/Search/20170404?format=json&isbnjan=${data}&applicationId=○○○○○`; fetchBooks(URL); }; const fetchBooks = async URL => { try { const response = await axios.get(URL); //本の情報を取得する setBookInfo(response.data.Items[0].Item); } catch (error) { alert("エラーが発生しました"); } }; if (hasPermission === null) { return <Text>Requesting for camera permission</Text>; } if (hasPermission === false) { return <Text>No access to camera</Text>; } const styles = StyleSheet.create({ barcode: { width: "100%", height: "40%" }, container: { flex: 1 } }); const resetSession = () => { setScanned(false); setBookInfo(null); }; return ( <SafeAreaView style={styles.container}> <BarCodeScanner onBarCodeScanned={scanned ? undefined : handleBarCodeScanned} style={styles.barcode} ></BarCodeScanner> {scanned && ( <Button title={"Tap to Scan Again"} onPress={() => resetSession()} /> )} {bookInfo !== null ? ( <> <Text>本のタイトル: {bookInfo.title}</Text> <Image source={{ uri: bookInfo.largeImageUrl }} style={{ width: 200, height: 200 }} /> </> ) : null} </SafeAreaView> ); }
実機で確認するといかのようになります。
感想
ネイティブアプリの機能でもExpoがAPIを提供してくれてありがたいなぁと思いました。