Edupala

Comprehensive Full Stack Development Tutorial: Learn Ionic, Angular, React, React Native, and Node.js with JavaScript

React typescript build wrapper component that render different elements

A React TypeScript build wrapper component is a powerful tool that allows developers to customize the rendering of various elements within their applications. This component is designed to wrap around other components and provide additional functionality or customization options.

In this artilces we are also learning Type predicate to render element based on type condition.

In order to keep a well-organized and modular codebase in React applications, it is crucial to create components that can be reused. To achieve this, wrapper components are often employed to render different elements dynamically depending on certain conditions or props. With TypeScript, developers can greatly improve the development process by taking advantage of its type safety and clear interfaces. In this article, we will delve into the design and implementation of such wrapper components in a React TypeScript project.

There are many different ways to use a build wrapper component in a React TypeScript application. For example, you might use it to add custom styling or behavior to a button component, or to create a complex layout for a form that includes multiple input fields and validation logic.

Understanding the Requirements:

Before diving into the implementation, let’s outline the requirements for our wrapper component:

  1. It should be a TypeScript functional component.
  2. The component should accept a prop indicating the type of element to render.
  3. Based on the value of this prop, the component should render the corresponding HTML element.
  4. Optional props like className or any other attributes should be supported.

React typescript wrapper component

Let first demonstrate an example for Typescript React conditional rendering based on condition.

import React from 'react';

interface WrapperProps {
  condition: boolean;
  // Other props as needed
}

const WrapperComponent: React.FC<WrapperProps> = ({ condition, children }) => {
  return (
    <div>
      {condition ? (
        <div>
          {/* Render element for condition true */}
          {children}
        </div>
      ) : (
        <div>
          {/* Render element for condition false */}
          {/* You can also render different components here */}
        </div>
      )}
    </div>
  );
};

export default WrapperComponent;

Now in parent component we ca called the wrapper component as.

import WrapperComponent from './WrapperComponent';

const App: React.FC = () => {
  const isLoading = true; // Example condition

  return (
    <WrapperComponent condition={isLoading}>
      {isLoading ? (
        <p>Loading...</p>
      ) : (
        <div>
          <p>Content here</p>
        </div>
      )}
    </WrapperComponent>
  );
};

Example 2 React typescript Wrapper component

Here is

import { ComponentPropsWithoutRef } from "react";

//SOLUTION 1
type ButtonProps = {
  el: "button";
} & ComponentPropsWithoutRef<"button">;

type AnchorProps = {
   el: "anchor";
} & ComponentPropsWithoutRef<"a">;

function Button(props: ButtonProps | AnchorProps) {
  const { el, ...otherProps} = props;
  if (props.el === "anchor") {
    return <a className="button" href="" {...props}></a>;
  }

  return (
    <button className="button" {...props}>
      Button
    </button>
  );
}

export default Button;

There are a few potential issues with this approach:

  1. Explicitness: The el property needs to be explicitly passed every time the Button component is used. This could be seen as redundant, especially when other properties (like href for anchors) are already indicative of the element type. <Button el=”button>… or <Button ele=”anchor” href=”..” > ..
  2. Type Safety: TypeScript cannot guarantee that the correct properties are passed for the specified el value. For example, if el is set to "anchor", but no href is provided, TypeScript won’t raise an error, even though an anchor without an href is semantically incorrect.

Type Predicate for Inference for above solution

We can leverages the href prop to infer the element type.

Type Predicate for Inference:

  • isAnchorProps function: Acts as a type guard, checking if the given props are of type AnchorProps based on the presence of the href prop.

The second solution addresses these issues by leveraging TypeScript’s type inference and type guards. The isAnchorProps function is a type guard that checks if the href property is present in the props, and if so, infers that the props are of type AnchorProps.

import { ComponentPropsWithoutRef } from "react";

type ButtonProps = ComponentPropsWithoutRef<"button"> & {
  href?: never;
};// not allow href attibute on button

type AnchorProps = ComponentPropsWithoutRef<"a"> & {
  href?: string;
}; //Present of href will not allow disabled on Anchor element

function isAnchorProps(props: ButtonProps | AnchorProps): props is AnchorProps {
  // Type predicate as return type is return boolean
  return "href" in props;
}

function Button(props: ButtonProps | AnchorProps) {

  if (isAnchorProps(props)) {
    return <a className="button" href="" {...props}></a>;
  }

  return (
    <button className="button" {...props}>
      Button
    </button>
  );
}
export default Button;

This approach has several advantages:

  1. Implicitness: There’s no need to explicitly specify the element type. It’s inferred from the presence or absence of the href property.
  2. Type Safety: TypeScript can guarantee that the correct properties are passed for each element type. If href is provided, it expects the other properties of AnchorProps to be passed as well, and vice versa for ButtonProps.
  3. Flexibility: This approach is more flexible and scalable. To support another element type, you just need to define a new props type and a corresponding type guard.
<Button>A Button</Button>
<Button href="https://google.com">A Link</Button>

type predicate isAnchorProps plays a key role in determining the element to render:

  • It takes either ButtonProps or AnchorProps as input.
  • It checks if the href prop exists in the provided props.
  • If href exists, it confirms the props are of type AnchorProps.
  • This information is used to conditionally render either an <a> (anchor) or <button> element in the Button component.
React typescript build wrapper component that render different elements

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top