🍣

【RN】react-native-hyperlinkで電話番号をリンク化する

2021/06/22に公開

はじめに

以前に以下のような記事を投稿しました。
https://zenn.dev/nekoniki/articles/7bc91d19f98cbacb0b63

内容はReactNative製のアプリにおいて、<Text>中に含まれるURLをハイパーリンク化するためにreact-native-hyperlinkというライブラリを導入した、というものです。

今回はその応用編で、テキスト中に含まれる「電話番号」をハイパーリンク化したいと思います。

linkifyを使う

react-native-hyperlinkのコンポーネントはデフォルトでいくつかのURLフォーマットに対応していますが、電話番号には対応していません。

https://github.com/obipawan/react-native-hyperlink

今回は"XXX-XXXX-XXXX"のような形式の電話番号をリンク化(タップした場合はそのままOS内臓の電話アプリを呼びだす)していきます。

react-native-hyperlinkのコンポーネントにはlinkifyというプロパティが用意されており、ここにリンク化したいフォーマットと判定方法を指定します。

linkifyにはlinkify-itというライブラリで定義されたオブジェクト形式で指定を行います。

https://github.com/markdown-it/linkify-it

linkify-itのインストール

下記コマンドからインストールを行います。
今回はTypescriptで実装を行うため@typesも追加してあります。

yarn add linkify-it
yarn add @types/linkify-it

判定処理を記載する

判定処理は少し癖のある書き方ですがLinkifyIt().add()で記載します。
判定の起点になる文字列を指定(ここでは電話番号の先頭文字である'0')して、続く文字列が目的の文字列であるかどうかを正規表現でチェックしています。

目的の文字列であることがわかった場合は、対象箇所の文字数をreturnすることでリンク化することができます。

タップした際は通常のリンクと同様にLinking.open()で問題ありませんが、電話番号の先頭にtel:を付けるのを忘れないようにしましょう。

App.tsx
import React from 'react';
import { Linking } from 'react-native';
import Hyperlink from 'react-native-hyperlink';
import LinkifyIt from 'linkify-it';

// 判定に使用する正規表現
const PHONE_REGEX = /^\d{2,3}-\d{1,4}-\d{4}/;

// 電話番号の文字列チェック処理
const PHONE_LINKIFY: LinkifyIt.LinkifyIt = LinkifyIt().add(
  // 判定を行う文字列(この文字列を含んでいる場合はvalidate)処理が走る
  '0', 
  {
    // リンク化したい文字列であるかどうかの判定処理
    validate: (text: string, pos: number) => {
      // text -> 文字列の全体
      // pos -> 目的の文字(ここでは'0')が存在するindex

      // 対象箇所の切り出し
      const target = '0' + text.slice(pos);
      // 切り出した箇所が目的の正規表現に合致していたらリンク化する
      if (target?.match?.(PHONE_REGEX)?.[0]) {
        // リンク化したい場合は「リンク化させたい文字数」を返却する
        return target.match(PHONE_REGEX)[0].length - 1;
      }
      return 0;
    },
    // 対象URLの整形処理
    normalize: (match: LinkifyIt.Match) => {
      // Linking.open用の"tel:"を付ける
      match.url = 'tel:' + match.url.replaceAll('-', '');
    },
  }
);

const App: React.VFC = props => {
  return(
      <Hyperlink
        linkify={PHONE_LINKIFY}
        linkStyle={{color: 'red'}}
        onPress={(url: string, text: string) => {
	  // リンクを開く
          Linking.openURL(url);
        }}>
        {`電話番号のリンク -> 000-0000-0000`}
      </Hyperlink>
  )
}

実際の表示

以下のようになりました。

phone_no

まとめ

今回はreact-native-hyperlinkの応用として、電話番号のハイパーリンク化の方法についてご紹介しました。
リンクであるかどうかの判定部分はlinkify-itに任せている部分が多いようで、そちらのフォーマットに合わせた指定をする必要があります。

今回紹介した方法が役立ちましたら幸いです。

Discussion