React - Components

Componentes que voy creando y puedo reusarlos en multiples proyectos

Stiven Castillo
3 min readMay 02, 2022

A veces creo estructura de componentes para proyectos en los que trabajo, pero con el tiempo olvido cómo los hice, por eso dejo esto y de una vez los comparto.

Iconos dinámicos

Los iconos en formato svg los tengo guardados en una carpeta assets/icons.

Creo un archivo iconNames.ts que contiene los nombres de los iconos (El nombre de los iconos es el mismo que en el archivo svg):

export type iconName =
  | 'icon_phone',
  | 'icon_home',
  ...

Archivo de los patchs de los iconos iconPaths.ts:

import IconPhone from './assets/icons/icon_phone.svg';
...

interface PathsTypes {
  [key: string]: any;
}

export const allPaths: PathsTypes = {
  icon_phone: IconPhone,
  ...
}

Y por último el componente Icon.tsx:

import React from 'react';
import { allIcons } from './iconNames';
import { allPaths } from './iconPaths';

export interface Props extends React.HTMLAttributes<HTMLDivElement> {
  name: allIcons;
  color?: string;
  width?: number;
  height?: number;
}

const Icon: React.FC<Props> = ({ name, color = "#009933", width = 15, height = 15, ...props }) => {
  const DynamicIcon = allPaths[name];

  return (
    DynamicIcon ?
      <DynamicIcon width={width} height={height} color={color} {...props} />
      : null
  )
}

export default Icon

Componentes poliformicos

La propiedad as se ha vuelto muy popular al construir componentes polifórmicos en React. Lo que permite esa propiedad es que podamos definir qué etiqueta HTML se pinte al renderizar el componente.

import React from "react";

type Rainbow =
  | "red"
  | "orange"
  | "yellow"
  | "green"
  | "blue"
  | "indigo"
  | "violet";

type AsProp<C extends React.ElementType> = {
  as?: C;
};

type PropsToOmit<C extends React.ElementType, P> = keyof (AsProp<C> & P);

// This is the first reusable type utility we built
type PolymorphicComponentProp<
  C extends React.ElementType,
  Props = {}
> = React.PropsWithChildren<Props & AsProp<C>> &
  Omit<React.ComponentPropsWithoutRef<C>, PropsToOmit<C, Props>>;

// This is a new type utitlity with ref!
type PolymorphicComponentPropWithRef<
  C extends React.ElementType,
  Props = {}
> = PolymorphicComponentProp<C, Props> & { ref?: PolymorphicRef<C> };

// This is the type for the "ref" only
type PolymorphicRef<C extends React.ElementType> =
  React.ComponentPropsWithRef<C>["ref"];

/**
* This is the updated component props using PolymorphicComponentPropWithRef
*/
type TextProps<C extends React.ElementType> =
PolymorphicComponentPropWithRef<
  C,
  { color?: Rainbow | "black" }
>;

/**
* This is the type used in the type annotation for the component
*/
type TextComponent = <C extends React.ElementType = "span">(
  props: TextProps<C>
) => React.ReactElement | null;

export const Text: TextComponent = React.forwardRef(
  <C extends React.ElementType = "span">(
    { as, color, children }: TextProps<C>,
    ref?: PolymorphicRef<C>
  ) => {
    const Component = as || "span";

    const style = color ? { style: { color } } : {};

    return (
      <Component {...style} ref={ref}>
        {children}
      </Component>
    );
  }
);

Post link: https://blog.logrocket.com/build-strongly-typed-polymorphic-components-react-typescript/