Aquí van preguntas y respuestas sobre sobre ReactJS que pueden ayudarte a preparar tu próxima entrevista o profundizar en algunos de los infinitos recovecos de esta criatura.
Cuestiones básicas, sin un orden particular.
Enjoy! 🔥🔥
¿El método setState() es asíncrono?
Sí. Si bien esta naturaleza puede no manifestarse claramente en muchos escenarios, el método setState()
es asíncrono ya que las acciones realizadas a través del mismo pueden ser agrupadas y atendidas en lotes.
React puede retrasar la actualización tras un setState()
o agrupar los cambios necesarios en lotes, por ejemplo, para renderizar varios componentes dependientes de forma simultánea. Este proceso transitorio busca un mejor rendimiento y no garantiza un comportamiento síncrono ni un renderizado inmediato del componente.
Esto puede derivar en que el acceso al estado inmediatamente después de invocar setState()
no muestre aún los cambios transferidos, pero varias de las configuraciones para setState()
evitarían esta situación.
¿Qué configuraciones admite setState()
?
El método setState()
admite tres posibles combinaciones de argumentos:
- Un único argumento en forma de objeto que pasaría a ser el nuevo estado del componente.
- Un único argumento en forma de función: un updater con dos parámetros por defecto (el estado actual y las props actuales) cuyo objeto retornado sería el nuevo estado del componente:
this.setState((state, props) => { return {counter: state.counter + props.increment} })
El objeto disponible como primer parámetro no debe ser mutado aquí: es un estado que sirve de referencia frente a cambios que dependan del propio estado antes de que haya sido actualizado, como en el ejemplo superior.
- Dos argumentos: un objeto que que pasaría a ser el nuevo estado del componente, y un callback que se invocaría una vez React haya procesado los cambios solicitados sobre el estado:
this.setState({counter: 10}, () => console.log(`Contador actualizado a ${this.state.counter}`))
¿Qué es el DOM virtual?
El DOM virtual o VDOM es un patrón de React basado en abstraer el DOM del navegador (también conocido como “DOM real” o “HTML DOM”) en una copia liviana que, almacenada en memoria, se encarga de sincronizar de forma constante con el DOM real. Esta copia virtual representa la UI.
Cuando un componente sufre un cambio en su estado, React hace uso de la API de Reconciliación para diferenciar en memoria qué ha cambiado. Este algoritmo diferencial permite detectar las variaciones, actualizando entonces el DOM real con los resultados de la comparativa.
Esta réplica virtual del DOM es conveniente en términos de agilidad frente al DOM real: carecer de los pesados detalles de implementación del navegador la hace más liviana y manejable. Básicamente, es más eficiente manipular un objeto que representa al DOM que al DOM en sí.
¿Qué son las referencias en React?
Las referencias o Refs
permiten a React manipular directamente el DOM sin necesidad de actualizar un componente.
Disponibles sólo en componentes de clase, asumen cambios en los mismos que no podemos resolver mediante el traspaso de props, o cuyo impacto se limita al propio componente no siendo rentable renderizarlo de nuevo.
Las referencias, creadas mediante createRef()
, se asocian a elementos del método render()
mediante la prop ref
, y se acceden mediante la propiedad current
de las mismas:
class AnimatedSpinner extends Component { constructor() { super() this.animationRef = React.createRef() // 1. creación } triggerAnimation() { this.animationRef.current.className.add('animated') // 3. acceso } render() { return ( <> <div ref={this.animationRef} className="spinner"> </div> // 2. asociación <button onClick={this.triggerAnimation}> Animar </button> > ) } }
El ejemplo anterior muestra cómo la referencia, con acceso a métodos del DOM como className.add()
, se establece en el método render()
pudiendo agregarle una clase sin manipular el estado.
¿Por qué es inviable retornar elementos adyacentes en JSX?
JSX es simplemente edulcorante sintáctico para generar elementos que, transpilados, dan lugar a su equivalencia en Javascript puro. El código que resulta de esta fase es una representación jerárquica del componente cuya estructura parental supone una limitación: sólo puede haber una raíz.
React, ahora sin JSX, entra en escena para procesar el código transpilado a través de su método createElement()
que es una implementación dotada de tres argumentos: tipo, props e hijos. Si bien podemos encontrar un número indeterminado de elementos adyacentes como hijos, todos ellos parten de un único elemento superior.
Podemos por tanto observar cómo este típico Hello world de JSX…
Hello world
…daría lugar a este resultado transpilado:
React.createElement('h1', {className: 'header-class'}, 'Hello world')
O cómo este ejemplo más completo…
Estoy anidado
…tendría una equivalencia donde se observa mejor cómo se desarrollan los diferentes hijos en el tercer argumento, comprendiendo asi que todos parten de un elemento único:
React.createElement( 'article', {className: 'article-class'}, React.createElement( 'h2', {className: 'title-class'}, 'Estoy anidado' ) )
¿React es una biblioteca o un framework?
React es una biblioteca que resuelve interfaces de usuario. Simplemente eso.
Una definición básica y comprensible de un framework sería un sistema donde incluyes tu código dando lugar a una aplicación. React, en cambio, es solo una parte mas de las que componen una aplicación.
Asume la capa de las vistas como otra de las dependencias que dan lugar a un producto.
¿Qué significa prop drilling y cómo evitarlo?
Las props que comparten componentes padres e hijos en la aplicación pueden acumular complejas dependencias. Este escenario, conocido como prop drilling, da lugar a flujos de datos profundos, difíciles de identificar y refactorizar.
Existen aquí dos formas de resolverlo:
- Composición de componentes frente a un mismo juego de datos compartido por varios componentes.
- Redux o la API Context, aptas en escenarios más complejos donde conviene propagar un estado global a través de la aplicación.
¿Qué son los fragmentos?
React no permite retornar elementos adyacentes en JSX. Esto se ha resuelto históricamente anidándolos en otros elementos que resuelven el problema pero generan código residual en el DOM.
Un fragmento es un componente presente en React que resuelve la problemática anterior sin agregar nodos extra y por tanto sin impacto sobre el DOM real.
Es común encontrarlo bajo su sintaxis reducida:
render() { return ( <> <h3>{props.title}</h3> <p>{props.detail}</p> </> ) }
Aunque su versión extendida agrega, además, compatibilidad con el atributo key
:
render() { return ( <React.Fragment key={props.id}> <h3>{props.title}</h3> <p>{props.detail}</p> </React.Fragment> ) } }
¿Qué función cumplen las keys en React?
Las keys o claves permiten diferenciar entre elementos únicos en el DOM virtual. Son favorables en términos de rendimiento al limitar la actualización del componente a las partes estrictamente necesarias.
Este recurso se utiliza fundamentalmente al generar elementos en una iteración (lista) donde la key
de cada elemento lo identifica de manera única. De esta forma, una actualización sobre el componente permitiría diferenciar los elementos cambiantes de los inmutados. React recicla así estos últimos que, si bien dependen del mismo componente, no se han visto afectados.
¿Qué objetivo cumple ReactDOM?
ReactDOM es una dependencia que actúa en el nivel superior de una SPA, conectando el ecosistema de React con el DOM del navegador.
Su función se basa en interactuar con el navegador para transferir al DOM real los cambios que React estipule en el DOM virtual.
¿Qué es el diseño atómico?
Una teoría basada en el modelo atómico-molecular que, aplicada a un contexto de composición, establece un marco de relaciones jerárquicas entre componentes: Átomos => Moléculas => Organismos => Sistema.
- Átomos: jerárquicamente inferiores y carentes de sentido por sí mismos. Ejemplos: títulos, iconos, textos o divisores.
- Moléculas: los elementos de menor jerarquía con información suficiente para resolver una necesidad específica del usuario sobre la interfaz. Nacen de la unión de dos o más átomos. Ejemplos: barras laterales, secciones, cabeceras o contenidos de una entrada.
- Organismos: las partes principales de un producto, fruto de la unión de dos o más moléculas. Cada página de una plataforma web es un ejemplo de organismo.
- Sistema: la totalidad del producto al combinar cada uno de sus organismos.
Es frecuente encontrar versiones de este patrón donde los organismos se equiparan a distribuciones y los sistemas a páginas:
¿Qué son los componentes controlados?
Son componentes que reciben información en forma de props y se valen de callbacks como onChange
para mutar el estado del componente padre, de cuyas props se nutren.
Enmarcados en este escenario cíclico, son también conocidos como dumb components.
Los campos de un formulario se ajustan claramente a esta definición: sus valores provienen del mismo estado que su propio callback muta en respuesta a la interacción del usuario.
¿Cómo limitar el alcance de los estilos en React?
Si bien React permite importar hojas de CSS ordinarias en componentes, esta tecnología tiene un alcance global que puede dar lugar a contaminación de estilos – a la vez que desaprovecha todas las funcionalidades dinámicas de una solución programática.
Algunas técnicas más avanzadas de estilizado en React delimitan el alcance de los estilos localmente, generando un namespace que da lugar a un tratamiento estético más predecible y modular.
Entre estas técnicas están los CSS Modules, bibliotecas CSS in JS o los clásicos estilos en línea, desaconsejados por afectar al rendimiento de React.
¿Qué función cumple shouldComponentUpdate()
?
El valor boleano retornado por el método shouldComponentUpdate()
controlaría la actualización de un componente, evitando su renderizado incluso frente a cambios en su estado o props.
¿Qué función cumple el componente StrictMode
?
El componente StrictMode
permite identificar problemas potenciales en la aplicación.
Puede ser integrado en cualquiera de los niveles de la misma para habilitar un modo seguro en sus componentes anidados, advirtiendo asi sobre el uso de recursos obsoletos, efectos colaterales o ciclos de vida inseguros, entre otros.
render() { return ( <StrictMode> <Componente1/> <Componente2/> </StrictMode> ) } }
Este componente no renderiza nada en la interfaz y limita su acción al entorno de desarrollo, perdiendo su vigencia en producción.
¿Deben favorecerse los componentes funcionales frente a los de estado?
Sí, siempre que sea posible. Hasta la entrada de React Hooks, la carencia de estado y de métodos para controlar el ciclo de vida de los componentes funcionales los ha relegado a un uso puramente representacional.
Hooks ha (casi) equiparado las funcionalidades de estos stateless components a los de clase, trazando una tendencia clara en la industria que prioriza su uso.
Algunos de los motivos para favorecer estas funciones frente a las clases serían:
- Sintaxis simplificada que facilita una creación y mantenimiento sencillos.
- Menor volumen de código en el propio componente.
- Menor volumen de código resultante tras su transpilación mediante Babel.
¿Qué diferencias existen entre el montaje y el renderizado de un componente?
- Montaje: React monta cada componente cuando este se muestra en la interfaz por primera vez. Es una fase única para cada componente. Este montaje está asociado a su método
constructor()
y culmina invocando su métodocomponentDidMount()
. - Renderizado: React renderiza un componente mediante
render()
la primera vez que se muestra así como en respuesta a los cambios en sus props o estado. Cada renderizado culmina invocando el métodocomponentDidUpdate()
correspondiente.