Tech blog Produced by FOURIER

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

Ohashi Ohashi 2022.10.17

はじめに

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

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

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

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

実装

早速実装していきます。まずはエラーを受け取って、エラーメッセージを表示する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」と表示されます。

See the Pen spectrum-web-analyzer by FOURIER Inc. ( @fourier-inc )on CodePen .

さいごに

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

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

Ohashi

Ohashi / Engineer

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