0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

トナカイ 一頭Advent Calendar 2024

Day 5

Suspenseとuse()とErrorBoundaryを使ったコードサンプル

Last updated at Posted at 2024-12-06

コード例

SuspenseSample.tsx
"use client";

import { FC, Suspense, use } from "react";
import { ErrorBoundary } from "../ErrorBoundary"

async function fetchWillError() {
  throw new Error
};

const ErrorFC:FC<{errorPromise:Promise<any>}> = ({errorPromise}) => {
  const data = use(errorPromise);
  return (
    <div>{JSON.stringify(data)}</div>
  )
};
const FallbackFC:FC = () => {
  return(
    <div>Loading...</div>
  )
};

export const PromiseErrorClient = () => {
  const errorPromise = fetchWillError();
  return (
    <>
      <ErrorBoundary>
        <Suspense fallback={<FallbackFC />}>
          <ErrorFC {...{errorPromise}}></ErrorFC>
        </Suspense>
      </ErrorBoundary>
    </>
  )
};

export default PromiseErrorClient

親コンポーネントで変数にPromiseを入れて、Suspenseの子コンポーネントにuseAPIで値を遅延読み込み。Promiseの失敗はErrorBoundaryコンポーネントで吸収する。
このコード例だと即時エラーをthrowしているが、ErrorBoundaryでwrapするだけでクラッシュを避けられる。

ErrorBoundary.tsx
import { Component, ReactNode } from 'react';

// Error Boudary Sample
export class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean; error: any }> {
  constructor(props: { children: ReactNode }) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: any) {
    return { hasError: true, error };
  }

  componentDidCatch(error: any, errorInfo: any) {
    console.error("Error caught in ErrorBoundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <div style={{ color: "red" }}>Error: {String(this.state.error.message || this.state.error)}</div>;
    }
    return this.props.children;
  }
};

:x:Bad Pattern

bad_pattern.tsx
/** bad pattern */
const ErrorFC:FC<{errorPromise:Promise<any>}> = ({errorPromise}) => {
  try {
    const data = use(errorPromise);
    return <div>{JSON.stringify(data)}</div>
  } catch(err) {  
      return <div>Error!</div>
  }
};

useをtry/catchで囲うなというエラーが出ます。

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?