React — Comprobando el tipo de dato de una prop con PropTypes

Mauricio Garcia
12 min readSep 29, 2020

--

Temario

  • Introducción.
  • ¿Qué es PropType?.
  • Validaciones básicas (Tipo de dato, Renderizables, Instancia, Múltiples).
  • Validaciones avanzadas (Arreglos, Objetos).
  • Validando datos obligatorios.
  • Validaciones personalizadas (básico, para arreglos y objetos)

i. PropTypes

Imaginemos que tenemos el componente Profile, donde va a recibir las siguientes propiedades: name,age.

Lo agregamos a la App, donde esperaríamos los atributos fueran así:

En pantalla:

Hasta aquí parece no hay problema, pero qué pasaría si el usuario o desarrollador manda lo siguiente:

Entonces, en pantalla:

Podemos observar que le mandamos atributos al componente con tipo de valores erróneos, en otros hasta hacen falta datos; y lo peor es que en consola no sale ningún tipo de error o advertencia…¿y ahora?

ii. ¿Qué es PropType?

PropTypes, mediante un objeto nos va a permitir agregar validaciones de tipo de dato a las props, asegurándose que la información recibida sea válida.

Importante PropTypes sólo verifica los tipo de dato en el entorno de desarrollo, por motivos de rendimiento no se activa en el entorno de producción.

A partir de la versión 15.5 de React, se volvió un paquete separado llamado prop-types[ref]. En caso de que estés haciendo una aplicación desde cero, debes de agregar el paquete a tus dependencias[ref]; si tu aplicación la creaste con create-react-app no es necesario cargarla, ya viene dentro de las dependencias.

:: Sintaxis de PropType

Debemos de importar el paquete y utilizar la sintaxis de arriba, en el componente que vamos a validar:

En el siguiente capítulo vamos a ver cómo se agregan las validaciones.

iii. Validaciones básicas

a — Tipo de dato

:: Tipos

  • PropTypes.string: Debe ser una cadena de texto.
  • PropTypes.number: Debe ser numérico.
  • PropTypes.bool: Debe se un booleano.
  • PropTypes.func: Debe ser una función.

Es muy común usarla en los componentes Form , donde manejamos desde el padre el evento que lanza el hijo.

  • PropTypes.array: Debe ser un arreglo.
  • PropTypes.object: Debe ser un objeto.
  • PropTypes.symbol: Debe ser un símbolo.
  • PropTypes.any: Cualquier tipo de dato (veremos un ejemplo más abajo)

:: Ejemplos

Aprovechemos el ejemplo anterior, si aplicamos las reglas, el componente funcional Profile quedaría de la siguiente manera:

Le estamos indicando que la propiedad name va a ser de tipo string y la propiedad age va a ser de tipo number, con estas validaciones, la consola nos va a arrojar mensajes de advertencia cuando los atributos mandados al componente no corresponda al tipo de dato que la propiedad espera.

Aumentemos complejidad al componente; imaginemos que vamos a mostrar el perfil de la persona, donde necesitamos los siguientes datos:

  • Nombre name:string
  • Edad age:number
  • Pasatiempos hobbies:array
  • Dirección address:object

Componente Profile :

Lo agregamos a la App:

Con este ejemplo, en la aplicación no nos a a mostrar ninguna advertencia, ya que los datos son del tipo correcto.

Vamos a mandarle a la propiedad name un número:

Podemos observar que SI muestra el componente (inclusive con name = 100), pero en consola nos arroja la advertenciaInvalid prop name of type number supplied to Profile, expected string.

Ver ejemplo (no olvides abrir la consola para ver las advertencias):

Crear las PropTypes,de los componentes, sirven como una documentación para el desarrollador que va a ocuparlo, ya que le indica las propiedades que recibe y el tipo de dato.

Con la imagen de arriba, te puedo decir que el componente Profile acepta las propiedades name:string, age:number, address:object, hobbies:array.

b — Renderizables

PropTypes, también hace validaciones a los componentes o elementos garantizando que React los pueda representar.

:: Tipos

  • PropTypes.node: Debe ser cualquier cosa que React pueda interpretar : número, cadena, elemento o arreglo.

Este llega a generar confusión con el PropTypes.any, pueden sonar a que son lo mismo, pero realmente no, veamos a detalle cada uno:

PropTypes.node: Todo aquello que pueda ser representado en pantalla por React, entonces antes de usarlo debemos hacer la pregunta : ¿Se puede ver en pantalla el tipo de dato “n”?

Si son posibles:

No son posibles:

El objeto, sí muestra name, por que en el componente esta propNode.name, pero si ponemos directamente propNode, se rompe toda la aplicación.

El NaN parece que sí lo acepta, pero te hace la sugerencia de que conviertas el valor a string.

El tipo PropTypes.node, es muy común utilizarlo cuando queremos dar la posibilidad de que nos pasen un componente o la clase de CSS del mismo:

PropTypes.any: Puede ser cualquier cosa

Todos ha pasado sin problemas, los mensajes de alerta que salen, el primero, es por que estoy intentando poner en pantalla una función (lo cual no debería), y el segundo es la sugerencia del NaN, entonces, ninguno de los dos errores son de validación de tipo de dato.

  • PropTypes.element: Debe ser un elemento React.

Sabemos que Babel compila JSX a llamadas de React.createElement(). Esto quiere decir que estos dos ejemplos son exactamente lo mismo:

React.createElement() internamente genera un objeto, ese objeto generado se le conoce como “Elementos de React”, que son descripciones de lo que queremos ver en pantalla (tipo, propiedades, color, etc), donde, React va a leer este objeto para construir el DOM y mantenerlo actualizado.

Entonces cuando pensemos en un elemento en react, debe ser como un objeto que tiene type, props, key, etc... , todos estos son elementos válidos:

Una vez que hemos comprendido el concepto de elemento, veamos como funciona PropType.element.

Inclusive podemos limitar a que el hijo children solo sea uno:

Sin validación:

Pero cuando agregamos la regla:

Como esta la validación, valida que NO tenga ningún hijo o SOLO uno:

  • PropTypes.elementType: Un tipo de elemento React

No debemos de confundirlo con PropType.element, recordemos que los elementos de React son objetos que van a describir lo que queremos en pantalla.

Admite todos los tipos de componentes (nativos, sin estado, con estado, referencias directas, providers), donde nos va a arrojar una advertencia cuando ninguno de ellos es un elemento, y el tipo de elemento es aquel que aún no tiene un objeto que lo defina como elemento, es un poco complicado de explicar, pero con el siguiente ejemplo, estoy seguro que te va a quedar más claro:

Un punto importante es que los tipos de elementos que estén construidos en React no llevan comillas, ya que internamente React mediante el JSX lo interpreta, mientras que un div es un componente nativo.

PropTypes.elementType se agregó a React a partir de la versión 15.7.0 [ref][ref][ref].

Mayormente es utilizado para crear componentes dinámicos, veamos un ejemplo con elementos nativos:

Con el componente de arriba, la idea es pasarle cualquier tipo de elemento nativo y sea capaz de renderizarlo, entonces, la App quedaría de la siguiente manera:

Ejemplo completo:

Ahora vamos a ver con elementos de React:

Tengo los siguientes componentes:

Entonces en la App tendríamos lo siguiente:

Ejemplo completo:

PropTypes.elementType, admite todos los componentes (nativos, sin estado, con estado, referencias directas, provider(context)), en caso de que no sea ninguno de esos elementos arrojará una advertencia, así como también cuando es un elemento y no un tipo.

c — Instancia

:: Tipos

  • PropTypes.instanceOf: No solo se limita a los valores primitivos y complejos, también podemos validar si una propiedad pertenece a una instancia de una clase JavaScript. React hace la comparación con instanceof que usamos normalmente en JavaScript, por lo cual nos asegura una validación correcta y el mejor rendimiento.

:: Ejemplo

Imagina que tenemos la siguiente clase:

En la aplicación importamos el componente Profile, que es a quien le pasamos la instancia de la clase User:

  • No olvidemos importar la clase User
  • Hacer la instancia de User

Ahora, el siguiente paso es validar que la instancia sea la correcta en el componente, por lo que :

  • No olvidemos importar la clase User (Es obligatorio, si no, no hay forma de validar)
  • Agregarlo en Profile.propTypes

Cuando la instancia es correcta, no sale ningún mensaje:

Cuando la instancia no coincide, sale un mensaje de advertencia:

d — Múltiples

:: Tipos

  • PropTypes.oneOf: Limitamos la propiedad a un conjunto específico de valores, donde se considera como enum, los valores deben de ir dentro de un arreglo PropTypes.oneOf([val1, val2, ...]), esto quiere decir que si vamos a pasar una propiedad al componente, debe de ser uno de los valores exactos permitidos.

enum: Un tipo de enumeración es un tipo de datos especial que permite que una variable sea un conjunto de constantes predefinidas. La variable debe ser igual a uno de los valores que se han predefinido para ella.

:: Ejemplo

Imaginemos que vamos a mostrar el perfil de la persona, donde necesitamos los siguientes datos:

  • Nombre name:string
  • Edad age:number
  • Género gender:oneOf, solo debe aceptar Female, Male

Componente Profile:

En la App vamos a mandar, primero atributos correctos:

Cuando nosotros mandamos un valor que no está dentro de los permitidos o no está exactamente escrito, nos arroja una advertencia:

Podemos observar que al primero le mandamos male en vez de Male, y en el segundo le estamos mandando Females cuando solo acepta Female, Male.

:: Ejemplo 2

Imagina que tenemos el componente Button, donde solo puede aceptar 3 tipos de botones primary, stroke, flat :

Y no solo estamos limitados a un solo tipo de valor, podemos mezclar:

  • PropTypes.oneOfType: La propiedad debe ser un conjunto específico de tipos de datos.

:: Ejemplo

Imaginemos que tenemos un Layout tipo Bootstrap[ref], Skeleton[ref], personalizado, donde tenemos el componente Container, donde recibe la propiedad fluid con solo dos tipos de datos boolean, string

La idea es de que si nos mandan true agregamos la clase container-fluid, si nos mandan un string, agregamos la clase container-{fluid}, en caso de que sea false no agregamos nada (ej. de un componente [ref]).

iv. Validaciones avanzadas

a — Arreglos

  • PropTypes.arrayOf()

En uno de los ejemplos anteriores, habíamos validado que la propiedad fuera un arreglo (PropTypes.array):

Pero ahora con PropTypes.arrayOf(), vamos a tener la oportunidad de indicarle qué tipos de datos son los que vamos a aceptar.

Entonces, el componente Profile, queda de la siguiente manera:

Y la App :

Podemos observar que en el atributo hobbies, en ambos estamos mandando un arreglo, solo que uno es tipo string y el otro es tipo number, entonces cuando revisamos la aplicación:

Nos sale la advertencia del arreglo de tipo numérico.

Ver ejemplo completo (revisar consola, para ver la advertencia):

Cuando queremos validar más de un tipo de dato, podemos combinarlo con PropTypes.oneOfType:

En el código de arriba, le estamos indicando que la propiedad multipleArrayProp va a ser de tipo array, donde va a aceptar solo 2 tipos de datos number y string.

b — Objetos

  • PropTypes.objectOf()

En uno de los ejemplos anteriores, habíamos validado que la propiedad fuera un objeto (PropTypes.object):

Pero ahora con PropTypes.objectOf(), vamos a tener la oportunidad de indicarle qué tipos de datos son los que vamos a aceptar.

Entonces, el componente Profile, queda de la siguiente manera:

La App:

Hasta aquí, ninguno de los dos contiene advertencias, ya que ambos están mandando los datos correctos; pero qué pasaría, si quisiéramos agregar el número de casa o departamento donde vive:

En el componente Profile :

En la App mandamos el número, dentro del atributo address:

En pantalla, nos sale la advertencia, debido a que le estamos indicando que addrees: PropTypes.objectOf(PropTypes.string) todas las propiedades sean de tipo string

Entonces podemos solucionarlo utilizando oneOfType, de la siguiente manera:

Pero el problema de hacerlo de esta forma, es que podríamos mandarle country o city un número y lo marcaría como válido, debido a que le estamos indicando que puede aceptar números o cadenas de texto:

Entonces, usaremos el siguiente método:

  • PropTypes.shape : Nos va a servir cuando queremos hacer una validación bastante detallada de un objeto, combinando claves con valores de tipo de dato específico.

Entonces, regresando a nuestro ejemplo, sabemos que:

  • country:string, city:string, number:number

Nuestra validación quedaría de la siguiente manera:

.

Y con esto estamos asegurando que cada una de las propiedades tenga el tipo de dato exacto que se requiere.

Ejemplo completo (revisar consola):

Podemos hacer una validación mezclando PropTypes:

Y la llamada del componente :

  • PropTypes.exact: El objeto debe venir con las propiedades exactas ó menos, pero no más.

En nuestro componente solo debemos cambiar el método shape por exact:

Ejemplo completo:

v. Validando datos obligatorios

Imaginemos que tenemos el componente Welcome:

Y queremos decirle al usuario o desarrollador que esa propiedad es obligatoria; con PropTypes es bastante sencillo, solo debemos encadenar isRequired, y con esto nos aseguramos que si no viene, nos lance la advertencia.

Nuestra App:

Toda propiedad que se requiera obligatoria, solo es necesario encadenar isRequired:

vi. Validaciones personalizadas

a — Básico

PropTypes, nos da la oportunidad de poner hacer validaciones personales (ej. email, rangos, datos correctos, etc).

:: Sintaxis

:: Ejemplo

Tenemos nuestro componente Welcome , donde recibe la propiedad name, la idea va a ser:

  • Validar que venga la propiedad.
  • Validar que tenga al menos 5 caracteres y no mayor a 50

Nuestro, componente sin la validación es el siguiente:

Podemos agregar la validación de dos formas:

  • Creando un archivo de validaciones, e importarlo en el componente:
  • La otra forma es agregando la función directamente:

Nota: Yo personalmente recomiendo tenerlos en un archivo aparte, con la finalidad de poner reutilizar y el código se vea más limpio.

En nuestra App:

Ejemplo completo:

:: Ejemplo 2

Imagina que dentro de children, nos van a mandar una lista, pero nosotros solo aceptamos <li> , entonces podemos hacer la validación:

Y en nuestro componente ListComponent:

Nuestra App

Ejemplo completo (ver consola):

b — Para arreglos y objetos

PropTypes, nos da la oportunidad de hacer validaciones personales de un arreglo arrayOf o un objeto objectOf.

:: Sintaxis

:: Ejemplo

Imaginemos que nos mandan un arreglo de edades, donde tenemos que validar que todas sean mayores a 18.

Nuestra validación:

Nuestro componente ListComponent:

Nuestra App:

Nos arroja un error en el segundo arreglo, ya que 13 es menor que 18.

Ejemplo completo:

Hasta aquí comprendimos, ¿qué es PropTypes?, las diferentes formas de validar los tipos de datos de las propiedades de un componente, así como también hacer nuestras propias validaciones.

--

--

No responses yet