Fundamentos y Conceptos Esenciales de React

Características Principales de React

  • Desarrollo declarativo
  • Compatibilidad con otras bibliotecas y frameworks
  • Arquitectura basada en componentes
  • Flujo de datos unidireccional
  • Biblioteca para la capa de visualización
  • Programación funcional

Props, State y el Método Rander

Cuando los datos en state o props cambian, la función render se ejecuta automáticamente. Cuando el componente padre vuelve a ejecutar su render, todos los componentes hijos también se renderizan nuevamente.

El DOM Virtual

El DOM virtual es una representación en formato de objeto JavaScript del DOM real. La comparación entre objetos JavaScript es mucho más eficiente que la comparación directa del DOM real.

Proceso tradicional sin DOM virtual:

  1. Tenemos datos en el state
  2. Tenemos una plantilla JSX
  3. Combinamos datos y plantilla para generar el DOM real y mostrarlo
  4. Cuando el state cambia
  5. Combinamos datos y plantilla nuevamente para generar un nuevo DOM real
  6. Reemplazamos completamente el DOM original

Problema: El reemplazo completo del DOM en cada cambio afecta significativamente el rendimiento.

Proceso con DOM virtual (enfoque recomendado):

  1. Tenemos datos en el state
  2. Tenemos una plantilla JSX
  3. Generamos un objeto que representa el DOM virtual
  4. Convertimos el DOM virtual en DOM real para mostrar
  5. Cuando el state cambia
  6. Generamos un nuevo DOM virtual basado en los datos actualizados
  7. Comparamos el DOM virtual anterior con el nuevo (algoritmo diff)
  8. Actualizamos únicamente las partes que cambiaron en el DOM real
// Estructura interna de render
render() {
    const { contenido, prueba } = this.props;
    // JSX -> createElement -> DOM Virtual (Objeto JS) -> DOM Real
    return (
        <div>
            <span>elemento</span>
        </div>
    );
    // Equivalente a:
    return React.createElement('div', {}, 
        React.createElement('span', {}, 'contenido')
    );
}

Ventajas del DOM virtual:

  • Mejora significativa del rendimiento
  • Permite aplicaciones multiplataforma (React Native, etc.)

Algoritmo Diff y Comparación de DOM Virtual

El algoritmo diff compara el DOM virtual anterior con el nuevo:

  • Compara a nivel de mismas capas (mismo nivel del árbol)
  • No utilizar el índice del array como clave (key={index})
  • Usar identificadores únicos como clave para cada elemenot
  • setState puede agrupar múltiples actualizaciones en una sola comparación

Manejo de Eventos y Referencias

Para capturar antradas del usuario y mantener sincronizado el estado:

<input 
    className="campo-busqueda" 
    type="search" 
    onChange={this.manejarCambio.bind(this)}
    onKeyUp={this.manejarTecla.bind(this)} 
/>

manejarCambio(evento) {
    const valor = evento.target.value.replace(/^\s+|\s+$/g, "");
    this.setState(() => ({ palabraClave: valor }));
}

manejarTecla(evento) {
    if (evento.keyCode === 13) {
        if (this.state.palabraClave.length > 1) {
            this.setState(() => ({ pagina: 1 }));
            this.obtenerDatos();
        }
    }
}

Uso de refs para acceder directamente a elementos del DOM:

<form className="formulario-datos" ref="formulario">
    <label>
        <i>*</i>Nombre del proyecto:
    </label>
    <input className="input-estilo" defaultValue={titulo} ref="tituloInput"/>
    <button 
        type="button" 
        className="boton-enviar" 
        onClick={this.enviarFormulario.bind(this)}
    >
        {this.state.tituloModal}
    </button>
</form>

enviarFormulario() {
    const { datosFormulario } = this.state;
    const inputTitulo = this.refs.tituloInput;
    const datos = {};
    
    if (inputTitulo.value.length < 2) {
        this.setState(() => ({ 
            mensaje: 'El nombre debe tener al menos 2 caracteres' 
        }));
    } else {
        datos.titulo = inputTitulo.value;
        
        if (datosFormulario.id) {
            datos.id = datosFormulario.id;
            this.actualizar(URL_ACTUALIZAR, datos);
            return;
        }
        
        this.setState(() => ({ datosFormulario: datos }));
        this.crear(URL_CREAR, datos);
    }
}

Llamar Métodos del Componente Hijo desde el Padre

Componente hijo:

import React from 'react';

export default class Notificacion extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            mensaje: ''
        };
    }
    
    componentDidMount() { 
        this.props.referencia(this);
    } 
    
    mostrarMensaje(texto) {
        this.setState(() => ({ mensaje: texto }));
        setTimeout(() => { 
            this.setState(() => ({ mensaje: '' })); 
        }, 3000);
    }
    
    render() { 
        return (
            <p className={this.state.mensaje.length > 0 
                ? "mensaje-activo" 
                : 'mensaje-oculto'}
            >
                {this.state.mensaje}
            </p>
        ); 
    }
}

Componente padre:

<Notificacion referencia={this.asignarReferencia} />

asignarReferencia = (ref) => {
    this.notificacion = ref;
}

// Llamar al método del hijo
this.notificacion.mostrarMensaje(respuesta.data.mensaje);

Método setState (Asíncrono)

this.setState((estadoAnterior) => ({
    elementos: [...estadoAnterior.elementos, valorInput],
    valorInput: ''
}), () => {
    // Este callback se ejecuta después de actualizar el state
    // Permite acceder a los datos recién actualizados
});

Métodos del Ciclo de Vida

Son funciones que React invoca automáticamente en diferentes momentos:

Fase de Montaje

  1. constructor(): Constructor del componente (ES6)
  2. componentWillMount(): Se ejecuta antes del montaje inicial. Solo se ejecuta una vez. Aquí se puede modificar el state.
  3. render(): Crea el DOM virtual y ejecuta el algoritmo diff. No modificar el state aquí.
  4. componentDidMount(): Se ejecuta después del montaje. Solo se ejecuta una vez. Ideal para llamadas API.

Fase de Actualización

Cuando cambian las props:

  • componentWillReceiveProps(nextProps): Se ejecuta cuando el componente recibe nuevas props del padre. La primera vez no se ejecuta.

Cuando cambian state o props:

  1. shouldComponentUpdate(nextProps, nextState): Retorna boolean. Permite optimizar rendimiento evitando renders innecesarios. Compara props y state anteriores con los nuevos.
  2. componentWillUpdate(nextProps, nextState): Se ejecuta antes de actualizar. Solo para actualización (no montaje). Puede modificar state.
  3. render(): Vuelve a renderizar el componente.
  4. componentDidUpdate(): Se ejecuta después de actualizar. Acceso al DOM disponible.

Fase de Desmontaje

  • componentWillUnmount(): Se ejecuta antes de remover el componente. Ideal para limpiar event listeners y timers.

Métodos Estáticos

// Configurar props por defecto
static defaultProps = {
    propiedad: 'valor'
};

Animaciones CSS en React

<p className={this.state.mensaje.length > 0 
    ? "visible" : 'oculto'}
>
    {this.state.mensaje}
</p>

/* Transiciones de visibilidad */
.visible {
    transition: all 0.5s ease-in;
    opacity: 1;
}
.oculto {
    transition: all 0.5s ease-in;
    opacity: 0;
}

/* Animación con cambio de color */
.visible {
    opacity: 1;
    transition: all 1s ease-in;
}
.oculto {
    animation: desaparecer 2s ease-in forwards;
}

@keyframes desaparecer {
    0% {
        opacity: 1;
        color: rojo;
    }
    50% {
        opacity: 0.5;
        color: verde;
    }
    100% {
        opacity: 0;
        color: azul;
    }
}

Biblioteca externa recomendada: react-transition-group para animaciones más complejas.

Fundamentos de Redux

Principios básicos:

  1. Solo debe existir un único store en la aplicación
  2. Solo el store puede modificar su propio contenido
  3. El reducer debe ser una función pura: dados los mismos argumentos, siempre devuelve el mismo resultado. No debe tener efectos secundarios ni modificar los parámetros de entrada.

API Principal de Redux

  • createStore: Crea el store central
  • store.dispatch: Envía acciones para actualizar el estado
  • store.getState: Obtiene el estado actual
  • store.subscribe: Suscribe una función que se ejecuta cuando cambia el estado

Tipos de Componentes

Comunicación de hijo a padre:

<div onClick={(indice) => {this.props.metodoPadre(indice)}}></div>

Categorías de componentes:

  1. Componentes presentacionales: Lógica y renderizado en el mismo lugar
  2. Componentes de lista: Lógica mínima + sin estado
  3. Componentes contenedores: Contienen la lógica principal
  4. Componentes funcionales sin estado: Solo renderizado, sin lógica
// Componente funcional sin estado
import React from 'react';

const ListaTareas = (propiedades) => {
    return (
        <div>
            <div>
                <Entrada 
                    valor={propiedades.valorInput} 
                    cambio={propiedades.manejarEntrada} 
                />
                <Boton clic={propiedades.enviar}>Agregar</Boton>
            </div>
        </div>
    );
};

export default ListaTareas;

Middleware en Redux

redux-thunk

  • Permite que las acciones sean funciones además de objetos
  • Extiende la funcionalidad de dispatch para manejar operaciones asíncronas

redux-saga

Alternativa a redux-thunk que utiliza generadores de JavaScript para manejar efectos secundarios de manera más declarativa.

Publicado el 6-21 05:36