Source

component/SuspenseWrapper/SuspenseWrapper.jsx

import React, { lazy, Suspense } from "react";
/**
 * A higher-order component that wraps child components in an error boundary
 * and provides a fallback loading UI using React Suspense.
 * @interface
 * @param {object} props - The component's props.
 * @returns {JSX.Element} The SuspenseWrapper component.
 */
const SuspenseWrapper = (props) => {
  return (
    <ErrorBoundary>
      <Suspense fallback={<Loading />}>{props.children}</Suspense>;
    </ErrorBoundary>
  );
};

export default SuspenseWrapper;
/**
 * Custom style for the loading component.
 */
const customStyle = {
  height: "100vh",
  width: "100vw",
  display: "flex",
  alignItems: "center",
  justifyContent: "center",
};
/**
 * A loading component displayed while the main content is loading.
 * @returns {JSX.Element} The Loading component.
 */
const Loading = () => <div style={customStyle}>Loading</div>;
/**
 * An error boundary component that catches errors in its children components.
 * @class
 */
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null, errorInfo: null };
  }
  /**
   * Catches errors that occur in the child components.
   * @param {Error} error - The error that was caught.
   * @param {object} errorInfo - Additional information about the error.
   */

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

  render() {
    if (this.state.errorInfo) {
      // Error path
      return (
        <div>
          <h2>Something went wrong.</h2>
          <details style={{ whiteSpace: "pre-wrap" }}>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }
    // Normally, just render children
    return this.props.children;
  }
}