LoginSignup
1
0

More than 1 year has passed since last update.

【React Native】簡単なAPI連携のアプリケーションを作成する ②住所検索の実装

Last updated at Posted at 2021-02-15

はじめに

本記事は下記の記事の続編になります。
【React Native】簡単なAPI連携のアプリケーションを作成する ①準備編
実践的なアプリを作成するというよりは、ハンズオン的にReact Nativeを触ってみるといった趣旨になっています。

本記事で説明すること

環境

  • axios:0.21.1

今回使用するAPI

Githubリポジトリ(追記:削除済み)

実装

それでは前回のソースから手直しを始めていきます。

axiosの導入

まずはnpmでaxiosをインストールします。

$ npm install axios --save

package.jsonを確認します。

package.json
{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "expo": "~40.0.0",
    "expo-status-bar": "~1.0.3",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
    "react-native-web": "~0.13.12"
  },
  "devDependencies": {
    "@babel/core": "~7.9.0"
  },
  "private": true
}

11行目にaxiosの記載があり、導入できていそうですね。
ではソースを修正していきます。

app.jsx
import React, { useState } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert } from 'react-native';
import axios from 'axios';

// 郵便番号検索APIのURL
const zipcloudURL = 'https://zipcloud.ibsnet.co.jp/api/search';

export default function App() {
  // 郵便番号を保存しておくstate
  const [postalCode, setPostalCode] = useState('');
  const [address, setAddress] = useState('');

  // axiosのGETメソッドを使った住所検索
  const fetchAddress = async () => {
    try {
      const response = await axios.get(`${zipcloudURL}?zipcode=${postalCode}`);
      const data = response.data;
      if ( !data.results ) {
        return '該当する住所はありませんでした。'
      }
      switch (data.status) {
        case 200:
          // 今回はテストなので、同じ郵便番号で2件以上存在する場合は除きます
          return `${data.results[0].address1}${data.results[0].address2}${data.results[0].address3}`;
        case 400:
          return data.message;
        case 500:
          return data.message;
      }
    } catch (error) {
       return '検索失敗';
    }
  }

  // 送信ボタンを押した時に実行される関数
  async function handlePress() {
    // 7桁の数字を正規表現で置きます
    const pattern = /^[0-9]{7}$/;
    if (pattern.test(postalCode)){
      const address = await fetchAddress();
      setAddress(address);
    } else {
      // 想定していない文字列の場合
      Alert.alert('正しい郵便番号ではありません', 'もう一度入力してください');
    }
  }

  // アプリに描画する内容
  return (
    <View style={styles.container}>
      <Text style={styles.description}>郵便番号を入力してください{"\n"}(ハイフンなし7桁)</Text>
      <TextInput
        value={postalCode}
        style={styles.inputPostalCode}
        onChangeText={(text) =>{
          setPostalCode(text);
        }}
        maxLength={7}
        keyboardType={"numeric"}
        placeholder={"郵便番号"}
      />
      <Button
        title="送信"
        color="#AAAAAA"
        onPress={handlePress}
      />
      {address.length > 0 && (
        <View style={styles.addressContainer}>
          <View style={styles.addressLabel}>
            <Text style={styles.addressLabelText}>住所</Text>
          </View>
          <View style={styles.address}>
            <Text style={styles.addressText}>{address}</Text>
          </View>
        </View>
      )}
    </View>
  );
}

// 各要素のスタイル
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  description: {
    fontSize: 18,
    color: '#666666',
    paddingBottom: 10,
  },
  inputPostalCode: {
    textAlignVertical: 'center',
    width: 120,
    fontSize: 24,
    marginBottom: 10,
    paddingLeft: 5,
    borderWidth: 1,
    borderColor: 'rgba(0, 0, 0, 0.2)',
  },
  addressContainer: {
    paddingVertical: 10,
    width: 280,
  },
  addressLabel: {
    paddingBottom: 10,
  },
  addressLabelText: {
    fontSize: 18,
    color: '#666666',
  },
  address: {
    paddingLeft: 5,
  },
  addressText: {
    fontSize: 16,
    color: '#000000',
  },
});

結構ソースが長くなってしまっています。今回はQiita用に長めに書いているのもありますが、
どの程度分割すべきかあまり分かっていない節はあります。

中身の解説

fetchAddressメソッドがaxiosを用いてAPIにリスエストする処理です。
通常は連結した住所の文字列をreturnします。
検索結果が0件の場合、data.resultsがnullになるのでその場合は0件のメッセージをreturnします。

また、送信ボタンを押したときの処理として、7桁の数字かを確認し、
変な文字列を入力していた場合にはアラートでユーザーに通知するようにしています。

レンダリングする処理についてはaddressの長さで判断し、検索後は住所を表示します。

動作確認

  • 初期画面
1初期画面.png
  • 正常に検索結果を表示
2正常系.png]
  • 数字以外の文字列の場合
3不正な文字列.png]        ↓ 送信ボタン押下 4アラート.png]
  • 検索結果が0件の場合
5存在しない郵便番号.png]

次回予告

あと1,2回で完結予定です。
ただ、次回はちょっと寄り道をしてESLint+Prettierの導入をしようと思います。
(今回ソースを書いててなかなか不便だったのと、備忘を兼ねて。。)

2021/2/20 続きを書きました。
【React Native】簡単なAPI連携のアプリケーションを作成する ③ESLint+Prettierの導入(寄り道)

2021/2/21 最終回を書きました。
【React Native】簡単なAPI連携のアプリケーションを作成する ④天気情報表示の実装

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0