Produced by Fourier

props.childrenに型付けしてpropsを渡す方法

Ohashi Ohashi カレンダーアイコン 2022.10.17

はじめに

React.js でエラー処理を行う場合、 ErrorBoundary という選択肢があるかと思います。

ErrorBoundary を使用する際に、 フォールバックコンポーネントに型付け した上でエラー情報を渡すにはどうすればよいか、悩んだことがあったので、今回記事を執筆しました。

私の場合は ErrorBoundary を使用する際に必要となりましたが、その他の場合でも活用できるので、最後まで読んでいただけましたら幸いです。

※本記事は ErrorBoundary について理解されている方を対象にしています。本記事では ErrorBoundary についての説明はしませんので、わからない方は、記事を読む前に 公式ドキュメント を一読ください。

https://ja.legacy.reactjs.org/docs/error-boundaries.html

実装

早速実装していきます。まずはエラーを受け取って、エラーメッセージを表示する DisplayErrorMessage コンポーネントを作成します。

動作確認をしやすくするため、 「Reset Error」 ボタンを設置します。このボタンを押すとエラーをリセットできます。

const DisplayErrorMessage = (
  { error, resetError }: { error: Error, resetError: () => void }
) => (
  <>
    <h1>{error.message}</h1>
    <button onClick={resetError}>{'Reset Error'}</button>
  </>
);

次にエラーをスローする ThrowError コンポーネントを作成します。 こちらも動作確認をしやすくするため、 「Throw Error」 ボタンを設置します。このボタンを押すことでエラーをスローします。

const ThrowError = () => {
  const [shouldThrow, setShouldThrow] = React.useState(false);
  
  if(shouldThrow) {
    throw new Error('Error');
  }
  
  return (
    <>
      <h1>No Error</h1>
      <button onClick={() => setShouldThrow(true)}>{'Throw Error'}</button>
    </>
  );
}

最後に ErrorBoundary コンポーネントを作成します。これで必要なコンポーネントが揃いました。

ここで重要なのが、エラーが発生した際に表示されるフォールバックコンポーネントを、関数を実行しレンダリングできるようにすることです。

そうすることで関数の引数からエラーを渡し、そのエラーをコンポーネントのpropsに設定することが可能となります。

import React from 'react';

type FallbackFunc = (error: Error, resetError: () => void) => React.ReactNode;

type ErrorBoundaryProps = {
  fallback?: React.ReactNode | FallbackFunc
  children?: React.ReactNode;
};

type ErrorBoundaryState = { 
  error: Error | null;
};

class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
  state: ErrorBoundaryState = { error: null };

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    this.setState({ error });
  }

  render() {
    if (this.state.error) {
      return typeof this.props.fallback === 'function'
        ? this.props.fallback(this.state.error, () => this.setState({ error: null }))
        : this.props.fallback;
    }
    
    return this.props.children
  }
}

ErrorBoundary  の fallback  プロパティに error  と resetError  を受け取り、返り値にそれらをpropsに設定した DisplayErrorMessage  コンポーネントを返すようにしています。

const App = () => (
  <ErrorBoundary 
    fallback={(error, resetError) => <DisplayErrorMessage error={error} resetError={resetError} />}
  >
    <ThrowError />
  </ErrorBoundary>
);

以下が実際に動作するデモになります。

「Throw Error」 ボタンをクリックすることで、 「No Error」 と表示されていた箇所が 「Error」 に変わることが確認できるかと思います。

また、 「Reset Error」 ボタンをクリックすることで、再度 「No Error」 と表示されます。

さいごに

props.childrenの値をReactNodeを返す関数にすることで、型付けした上で親コンポーネントから子コンポーネントへpropsを渡すことができるようになりました。

方法としては単純ですが、意外と思いつかなかったりするものではないでしょうか。もしこの方法が必要になりましたらぜひ使用してみてください。

Ohashi

Ohashi slash forward icon Engineer

主にLaravelなどのバックエンドを中心にサーバー周りも担当しています。目標は腕周り40cm 越え。

関連記事