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

ReactでLIFFアプリケーションの初期開発

どもども!今回は、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のほうもよろしくお願いします。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

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

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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です