Next.jsのError Boundaryについて

# Error Boundaryとは

Reactドキュメントより以下のようにありました。

>error boundary は自身の子コンポーネントツリーで発生した JavaScript エラーをキャッチし、エラーを記録し、クラッシュしたコンポーネントツリーの代わりにフォールバック用の UI を表示する React コンポーネントです。

# 公式のNext.jsのError Boundaryについて

[Next.jsのError Boundaryのページ](https://nextjs.org/docs/pages/building-your-application/configuring/error-handling)ではError Boundaryについて解説してあります。

簡単に説明するとError Boundaryというコンポーネントを作成し、それを`_app.jsx`でwrapしてくださいということです。

```jsx:ErrorBoundary.jsx
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
 
    // Define a state variable to track whether is an error or not
    this.state = { hasError: false }
  }
  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI
 
    return { hasError: true }
  }
  componentDidCatch(error, errorInfo) {
    // You can use your own error logging service here
    console.log({ error, errorInfo })
  }
  render() {
    // Check if the error is thrown
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return (
        <div>
          <h2>Oops, there is an error!</h2>
          <button
            type="button"
            onClick={() => this.setState({ hasError: false })}
          >
            Try again?
          </button>
        </div>
      )
    }
 
    // Return children components in case of no error
 
    return this.props.children
  }
}
 
export default ErrorBoundary
```

```jsx:_app.jsx
// Import the ErrorBoundary component
import ErrorBoundary from '../components/ErrorBoundary'
 
function MyApp({ Component, pageProps }) {
  return (
    // Wrap the Component prop with ErrorBoundary component
    <ErrorBoundary>
      <Component {...pageProps} />
    </ErrorBoundary>
  )
}
 
export default MyApp
```

私もこれで実装しようとしたのですが、エラー文が全部取得できなかったり
、挙動が狙ったようにならないため断念しました。
あとは、`TypeScript`のサンプルが全然ないことです。(あるにはあります)

# react-use-error-boundaryの導入

Next.jsのエラーハンドリングはIssueでも議論されていることを知り、そこで` react-use-error-boundary`というライブラリが紹介されていたので使用してみたらとても良かったので紹介します。

## インストール
```
yarn add react-use-error-boundary
```

## 使用方法
エラーをキャッチしたいコンポーネントで`withErrorBoudnary()`をラップします。

つまり以下のような_app.tsxの場合

```tsx
import type { AppProps } from 'next/app';

const App = ({ Component, pageProps }: AppProps) => {
  return (
    <Component {...pageProps} />
  );
};

export default App;
```
```diff_tsx:_app.tsx
import type { AppProps } from 'next/app';
import { useErrorBoundary, withErrorBoundary } from 'react-use-error-boundary';
import sendToMyService from '@/utils/sentry';

const App = withErrorBoundary(({ Component, pageProps }: AppProps) => {
  const [error, resetError] = useErrorBoundary(async (error) => {
    sendToMyService(error);
  });

  return (
    <Component {...pageProps} />
  );
});

export default App;
```

このようにすればOKです。エラーメッセージはerrorに格納されています。

あとはnodemailerやsentryなどに送信すればOKです。

また、エラーをリセットしたい場合はresetError関数が呼べるのでエラーハンドリングが終わったタイミングで呼び出すことができます。

また、errorで条件分岐すればエラー画面に飛ばすこともできます。

```tsx
import type { AppProps } from 'next/app';
import { useErrorBoundary, withErrorBoundary } from 'react-use-error-boundary';
import sendToMyService from '@/utils/sentry';

const App = withErrorBoundary(({ Component, pageProps }: AppProps) => {
  const [error, resetError] = useErrorBoundary(async (error) => {
    sendToMyService(error);
  });

  if (error) {
    return (
      <>ERROR PAGE</>      
    )
  }

  return (
    <Component {...pageProps} />
  );
});

export default App; 
```


## このライブラリの良い点

良かったことはエラーハンドリングも関数コンポーネントでかけること、いちいちErrorBoudaryを書かなくていいこと、TypeScriptをサポートしていることです。


# 参考文献

https://www.npmjs.com/package/react-use-error-boundary