【React】LINE LIFFアプリの初期開発:エラーハンドリングとHooks

ReactでLIFFアプリケーションの初期開発
◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

どもども!今回は、LIFF(LINE Front-end Framework)アプリケーションをReactで開発する際の初期開発のセットアップを行いました。SWRとreact-error-boundayのエラーハンドリングとLIFFから情報を取得する部分をHooksとしてまとめておきました。LIFFを運用するために必要な設定なので、是非ご一読!

はじめも

どもども!本日三台目の救急車が家の前を通りすぎている龍ちゃんです。メイン通りから一本入ったところなんですけど、病院が近いこともあって救急車は大量に通ります。この辺は、住んでからじゃないとわからないところですね。さて…いろんなことが同時並行で進んでいるので、頭がパンクしないか不安に駆られています。

さて、今回もLINEのLIFF(LINE Front-end Framework:以降LIFF)に関する内容になります。前回は、LIFFアプリケーションの開発環境構築について記事にしました。今回の記事では、もっとフロントエンド寄りの内容について書いていきます。デフォルトのアプリケーションから、実際の開発スタイルに寄せていきます。

今回対応した内容としては、以下になります。

  • LIFFアプリケーションのエラーのエラーハンドリング
    • liff.initをコンポーネントとして分離する
  • LINE内のブラウザ以外で起動した場合は、LINEに誘導をする
  • LIFFアプリケーションで取得することができる情報をHooksにまとめる
    • SWRを用いてLINEログイン者情報を取得する

それでは、順番に取り組んでいきたいと思います。こちらの記事は、2つの記事をベースに構成されています。

LIFFアプリのカスタマイズ

今回は、以下のディレクトリ構造で取り組んでいきます。

src/
├── App.tsx
├── hooks
│   └── useAuth.ts
├── index.css
├── main.tsx
├── pages
│   ├── NotfoundPage.tsx
│   ├── TopPage.tsx
│   └── layouts
│       └── ParentLayout.tsx
├── router
│   └── RouterConfig.tsx
├── utilities
│   ├── ErrorBoundary.tsx
│   ├── LiffInit.tsx
│	  └── SwrConfig.tsx
└── vite-env.d.ts

必要なライブラリとしては、以下になります。必要に応じてインストールしてください。

# ReactでSPAにするために
yarn add react-router-dom

# データフェッチ用ライブラリ
yarn add swr

# エラーハンドリング
yarn add react-error-boundary

LIFFアプリケーションのエラーハンドリング

LIFFアプリケーションのハンドリングを行うための設定を行います。まずは、コンポーネント設計を図にしたのでおいておきます。

エラーハンドリングのコンポーネント設計

今回は、react-error-boundaryを用いてエラーを一元管理しています。utilities内のErrorBoundary.tsxの内容が以下になります。

import { ErrorBoundary, FallbackProps } from "react-error-boundary";

type Props = {
  children: React.ReactNode;
};
export const ErrorBoundaryComponent = (props: Props) => {
  const { children } = props;

  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>{children}</ErrorBoundary>
  );
};

const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
  console.error(error);
  return (
    <>
      <button className="" onClick={resetErrorBoundary}>
        リトライ
      </button>
    </>
  );
};

データ取得はSWRを用いた管理をするため、SWRのエラーをreact-error-boundayに伝搬させる必要があります。同じくutilites内のSwrConfig.tsxの内容が以下になります。

import { useErrorBoundary } from "react-error-boundary";

import { SWRConfig } from "swr";

type Props = {
  children: React.ReactNode;
};

export const SWRConfigComponent = (props: Props) => {
  const { children } = props;
  const { showBoundary } = useErrorBoundary();
  return (
    <SWRConfig
      value={{
        onError(err) {
          showBoundary(err);
        },
      }}
    >
      {children}
    </SWRConfig>
  );
};

react-error-boundayが提供しているuseErrorBoundary()を使用してSWRでキャッチしたエラーを伝搬させます。

import { useErrorBoundary } from "react-error-boundary";

const { showBoundary } = useErrorBoundary();
showBoundary(err);

こちらのHooksを呼び出すことで、任意のタイミングでエラー画面へ遷移させることが可能になります。

最後に、LIFFアプリケーションのセットアップ用の構築を行います。同じくutilites内のLiffInit.tsxの内容が以下になります。

import liff from "@line/liff";
import { useEffect, useState } from "react";
import { useErrorBoundary } from "react-error-boundary";

type Props = {
  children: React.ReactNode;
};

export const LiffInit = (props: Props) => {
  const { children } = props;
  const { showBoundary } = useErrorBoundary();

  const [liffInit, setLiffInit] = useState<boolean>(false);

  const isInLineClient = liff.isInClient();

  useEffect(() => {
    liff
      .init({
        liffId: import.meta.env.VITE_LIFF_ID,
      })
      .then(() => {
        setLiffInit(true);
        console.log("LIFF init succeeded.");
      })
      .catch((e: Error) => {
        setLiffInit(false);
        showBoundary(e);
      });
  });
  if (!liffInit) {
    return <>Loading now</>;
  }
  if (!isInLineClient) {
    return <>Please open in LINE ここでQRの画像を出すのはありでは?</>;
  }
  return <>{children}</>;
};

こちらでは、LIFFアプリケーションの初期化を行っています。初期化が失敗した場合は、SWRの場合と同じくreact-error-boundayが提供しているuseErrorBoundary()を使用してエラーを伝搬させます。あとは、以下のファイルをlayoutとして保存します。

import { Outlet } from "react-router-dom";

import { ErrorBoundaryComponent } from "@utilities/ErrorBoundary";
import { LiffInit } from "@utilities/LiffInit";
import { SWRConfigComponent } from "@utilities/SwrConfig";

export const ParentLayout = () => {
  return (
    <>
      <section className="">
        <main>
          <ErrorBoundaryComponent>
            <SWRConfigComponent>
              <LiffInit>
                <Outlet />
              </LiffInit>
            </SWRConfigComponent>
          </ErrorBoundaryComponent>
        </main>
      </section>
    </>
  );
};

これによって、Outlet内で発生したReactのエラーはreact-error-boundayに吸収され、SWRとLIFFセットアップのエラーも同様に吸収されます。使用方法としては、react-router-domで構成しているConfigファイルでトップとしてParentLayout.tsxを設定することで機能します。

LINE内のブラウザ以外で起動した場合は、LINEに誘導をする

こちらは、ライブラリに搭載されている。liff.isInClient()を使用して実装することができます。公式ドキュメントはこちらにあります。こちらの値がTrueの場合は、LINE内部ブラウザになります。

utilites内のLiffInit.tsx内で表示を切り替えることで、外部ブラウザからのアクセスの場合は、QRやLINEアカウントへのリンクを表示することで「LINE内部ブラウザで起動した場合は、LINEに誘導する」ことができます。

LIFFアプリケーションで取得することができる情報をHooksにまとめる

ここでは、情報取得や内部で使いまわしそうな情報をHooksにまとめていきたいと思います。データの取得部分をSWR経由で取得しています。

import liff from "@line/liff";
import useSWRImmutable from "swr/immutable";

export const useAuth = () => {
  const accessToken = liff.getAccessToken();
  const idToken = liff.getIDToken();

  const { data: profile, isLoading: isProfileLoading } = useSWRImmutable(
    "liff/profile",
    () => liff.getProfile()
  );

  return { accessToken, idToken, profile, isProfileLoading };
};

アクセストークンとIDトークンを取得しておきます。これは、サーバー側でLINEの情報をセキュアに運用するために必要となる情報です。

profile内には以下の情報が含まれます。

  • userId:ユーザーID
  • displayName:表示名
  • pictureUrl:画像のUrl
  • statusMessage:ステータスメッセージ

こちらは、LINE内で設定している情報になります。その一方で、こちらの情報はサーバーに送信することが公式から止められています!!そのために必要となるのが、アクセストークンとIDトークンになります。

おわりも

ども!今回は、LIFFのアプリケーションの初期開発としてエラーハンドリングやHooksの設定を行いました。エラーハンドリングなどは、一番最初に設定するべきです。でも、開発を進めていかないと気付くことができないものですよね。やっぱりフロントエンドの開発は難しいですね。

これからは、LIFFアプリの情報をちょこちょこっと投稿していきます。

Twitterのほうもよろしくお願いします。

アバター画像
About 龍:Ryu 107 Articles
2022年入社で主にフロントエンドの業務でTailwindと遊ぶ日々。お酒とうまいご飯が好きで、運動がちょっと嫌いなエンジニアです。しゃべれるエンジニアを目指しておしゃべりとブログ執筆に注力中(業務もね)//
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる