Tipos de datos en React

Siguiendo con el uso de props vamos a definir como definir a que tipo de dato pertenecen nuestros props.

Esto aunque parece más trabajo ayuda a documentar nuestros componentes para que tanto otros desarrolladores, como nosotros mismos en el futuro, podamos saber que recibe un componente y no encontrarnos con errores.

Hay, como todo en JavaScript, varias formas de definir tipos de datos en React.

TypeScript

Una forma es usar TypeScript en vez de JavaScript normal, TypeScript es un lenguaje de programación que extiende JavaScript para agregar, entre otras cosas, tipos de datos al lenguaje los cuales son detectados por su compilador para ayudarte a prevenir errores durante el funcionamiento de la aplicación.

interface Props {
  name?: string;
}

function Hello({ name = "Mundo" }: Props) {
  return React.createElement("h1", null, `Hola ${props.name}!`);
}

En este caso ya que usamos TypeScript es más común usar funcionalidades propias del lenguaje para, por ejemplo, definir valores por defecto a un prop.

Si querés aprender TypeScript te recomiendo leer su documentación en https://www.typescriptlang.org/.

FlowType

Similar a TypeScript, FlowType extiende JavaScript para agregar tipos de datos, en este caso solo hace esto. Sus tipos son usados también al momento de compilar para detectar errores.

type Props {
  name?: string,
}

function Hello({ name = "Mundo"}: Props) {
  return React.createElement("h1", null, `Hola ${props.name}!`);
}

Si querés aprender FlowType te recomiendo leer su documentación en https://flow.org/.

PropTypes

PropTypes es la forma propia de React que funciona sin necesidad de compilar y de usar otro lenguaje de programación. Originalmente venía incluído en el mismo React, actualmente dada la popularidad de TypeScript y FlowType se separó en una librería externa para reducir el tamaño de React, así solo quienes usen PropTypes lo cargan.

Para cargarlo en nuestro proyecto es igual que hicimos con React y ReactDOM.

<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.2/prop-types.min.js"></script>

Una etiqueta <script> con el link para cargarlo desde un CDN.

Ahora vamos a tipar nuestro componente, para eso vamos a agregarle una propiedad estática llamada propTypes que va a ser un objeto donde cada key es un prop y su valor es el tipo de dato.

function Hello(props) {
  return React.createElement("h1", null, `Hola ${props.name}!`);
}

Hello.propTypes = {
  name: PropTypes.string
};

Hello.defaultProps = {
  name: "Mundo"
};

Con esto acabamos de definir que el prop name debe ser un string. Si ahora pasamos cualquier otro valor React nos va a mostrar en la consola de nuestro navegador un error de tipo de dato.

Al igual que hay PropTypes.string hay muchos otros tipos de datos dependiendo de nuestras necesidades.

PropTypesDescripción
arrayUn array normal de JavaScript ([])
boolUn true o un false
funcUna función (normal, arrow, generador o async)
numberUn número, tanto entero como con decimales, positivo o negativo
objectUn objeto plano de JavaScript ({})
stringUna cadena de caracteres
symbolUn símbolo creado con Symbol()
nodeUn nodo, puede ser cualquier hijo válido en React
elementUn elemento de React (el resultado de React.createElement)
instanceOf(Class)Una instancia de la clase Class
oneOf(['React', 'Redux'])Uno de varios valores fijos posibles
oneOfType([string, number])Uno de varios tipos de datos posibles
arrayOf(number)Un array del tipo de dato especificado
objectOf(number)Un objeto cuyos valores sean del tipo de dato especificado
shape({ name: string })Un objeto con la forma específicada
anyCualquier tipo de dato

Nota: Normalmente shape es mejor que object u objectOf ya que nos permite especificar la forma exacta que debe tener el objeto que vamos a recibir como prop.

Adicionalmente es posible crear PropTypes personalizados para hacer validaciones propias sobre los props. Esto lo veremos más adelante.

Props Obligatorios

También es posible definir un prop como obligatorio para que, en caso de no estar definido, React muestre un error avisando que es obligatorio.

function Hello(props) {
  return React.createElement("h1", null, `Hola ${props.name}!`);
}

Hello.propTypes = {
  name: PropTypes.string.isRequired
};

Como vemos, es cuestión de agregar .isRequired al tipo de dato para hacerlo obligatorio, otra efecto de esto es que podemos sacar el defaultProps ya que al ser obligatorio estamos seguros de que el usuario de nuestro componente va a definir siempre name y si no lo hace no nos molesta que falle el componente pues está marcado como obligatorio.

Palabras finales

Con todo esto nuestro ejemplo pasaría a ser igual es esto:

function Hello(props) {
  return React.createElement("h1", null, `Hola ${props.name}!`);
}

Hello.propTypes = {
  name: PropTypes.string
};

Hello.defaultProps = {
  name: "Mundo"
};

const element = React.createElement(Hello, { name: "Sergio" });
const node = document.getElementById("app");

ReactDOM.render(element, node);

Ya vimos como hacer un componente que use props, definir valores por defecto y ahora especificar el tipo de datos.

En próximos artículos veremos como hacer composición de componentes de React.