Entendimiento en React [v2]

En este articulo entenderemos un poco de React

0. Que es y como funciona

Podemos entender que React es un creador de interfaces. Normalmente, y aquí, lo usaremos para desarrollo web; pero React no se limita a esto, ya que podemos desarrollar interfaces para apps, aplicaciones de escritorio.

Ahora bien, React no es un fremaework como tal, es una librería que facilita el desarrollo de interfaces.

Para desarrollar para el entorno web, debemos conocer JSX y un empaquetador, el cual sera vite.

0.1 Crear un app con React + JSX + SWC

En nuestro entorno de desarrollo, en la consola escribiremos:

Crear react proyect
1. Usamos primero el comando: npm create vite@latest
2. Seleccionamos las caracteristicas, como nombre, react y JS + swc.
3. Ahora en la carpeta le damos npm install
4. Y para iniciar npm run dev

Porque JS + SWC, sera posiblemente el nuevo estándar ya que es mas eficiente, eso si no cambia nada en JS. (También esta TS + SWC por si les gusta esta otra opción).

0.2 Funciones

Algo que se complica es usar una función con o sin paréntesis, es así:

  • Ejemplo: funcion - Así, pasa la función para que otro la use, pero no se activa.
  • Ejemplo: funcion() - Así, se ejecuta la función normalmente.


1. Componentes

Es la forma básica en React, todo son componentes, veremos un ejemplo:


En la imagen podemos decir que, cada cuadro es un componente: con imagen, un texto y una etiqueta. Ademas tenemos otro componente que es el titulo.

Los componentes son para facilitar el desarrollo y la reutilización, como el ejemplo anterior tenemos 3 elementos diferentes pero con la misma base.

Para crear un componente haremos:

import useLikeFood from "../hooks/useLikeFood";

export default function Food({id, nombre, precio, disponible, imagen, evento}) {

    const {gusta, MeGusta} = useLikeFood(id);

    function MostrarMas(e) {
        e.stopPropagation();
        evento(id);
    }

    function AgregarMeGusta() {
        MeGusta();
    }

    return(
        <div className="Food" >
            <figure onClick={AgregarMeGusta} className= {gusta ? "Food_like_yes" : "Food_like"} ></figure>
            <h3>{nombre}</h3>
            <p>${precio}</p>
            <img src={imagen} alt="" />
            <button onClick= {MostrarMas}>
                {/* <Link to={`/detalle/${id}`}>Mas info</Link> */}
                Mas info
            </button>
        </div>
    );
}

Tenemos nuestras importaciones, luego el componente con sus props, funcionalidad del componente, luego se retorna (crea) el elemento con las variables.

Algo importante en términos, los elementos son diferentes a componentes.

  • Elemento: es un objeto fijo, en este caso HTML.
  • Componente: es un creador de elementos.

2. Estados

Son un elemento importante en React, ya que mantienen la informacion a lo largo del tiempo. Ya que las variables normales no mantienen su informacion cuando, por ejemplo, cambiamos de pagina.

Para crear una variable con estado:


import { useState } from "react";
const [foods, setFoods] = useState("Papitas");
 

Importamos el hook...

En una constante; ponemos el nombre de la variable; luego la función SET de la misma variable; y lo igualamos al hook importado y debemos asignarle un valor de inicio. (es importante que al usar los sets, se use exclusivamente una variable y no una operación)

Así, logramos que la variable no cambie durante el uso de la pagina. Y algo importante es que los estados al cambiar cambiaran los componentes, esta reactividad se enfoca exclusivamente en los componentes que cambiaron, dando optimización en la pagina con React. Esto lo podemos ver, cuando en una pagina web, cuando le damos a un elemento, solo cambia este y no se recarga toda la pagina.

2.1 Hooks

Son herramientas pequeñas reutilizables. Nosotros mismos podemos crearlas respetando la escritura: useEjemploHook. Ejemplo: el mismo useState.

2.1.1 UseEffect

Es un hook, el cual ejecuta un código (callback) hecho por nosotros, según un parámetro dado, ejemplo:


import { useEffect } from "react"

  useEffect(() => {
    console.log("Ejecutando el useEffect");
   
  }, [var1, var2])

Entonces, el ejemplo anterior el hook se ejecuta cada vez que alguna de las variables 'var1' o 'var2' cambie.

El hook, en su segundo parámetro puede recibir:

  • Una o mas variables: cada vez que alguna de estas cambie, se ejecuta el callback.
  • Lista vacía: otra forma, la cual ejecuta el código, cada vez que hay un cambio.

Un ejemplo clásico para obtener datos de una API:

 
useEffect(() => {        

        fetch("URL API")
            .then(res => res.json())
            .then(data => setData(data))
            .catch(err => console.log(err))
    }, []);
 

Algo importante, es que el hook debe cumplir una única tarea, no varias.

2.1.2 useRef

Guardar algo, la cual se mantiene mientras viva el componente, y cuando cambia no renderiza, esto evita el reinicio de la referencia.

Por ejemplo, tenemos un sistema de búsqueda y queremos que no se pueda hacer 2 veces la misma búsqueda. 


const previousSearch = useRef(search)

if(search !== previousSearch.current) {
    // Consumir API ejemplo
}
 

Entonces, se guarda la búsqueda (y como 'useRef', no cambia aunque se renderize el componente, que es lo que hace en cada búsqueda, podremos saber si es lo mismo o no)


2.1.3 useMemo

Es parecido a useEffect, necesita una función callback y un parámetro de cambio. Usado para optimizar renderizados en la pagina. Entonces, si el parámetro cambia: ejecuta la función. Si no cambia: no se ejecuta. 

La diferencia, que memoriza lo obtenido de esta función y lo guarda hasta que el parámetro cambie. Ejemplo:


const filtro = useMemo(() => {
        return // Retornar algo a guardar
    }, [variable])
 

2.1.4 useId

En React al usar tantos  componentes, algunos de las etiquetas usan id, por ejemplo un formulario, crear múltiples elementos, entonces, entre mas grande la aplicación los id podrían repetirse y ejecutar acciones imprevistas dañando la web. Lo evitaremos con este hook.

const precioId = useId()
   
    return(
            <div>
                <label htmlFor={precioId}>Precio:</label>
                <input
                    type="range"
                    id={precioId}
                    min="0"
                    max="4000"
                />
            </div> )

En el ejemplo anterior, creamos un id único en nuestro pequeño formulario, evitamos en un futuro repetir el id y dañar el sistema y también hacer cosas raras, como usar un randomizador, o escribir un id largo y complicado, etc...

 

2.1.5 useContext

Es una forma de evitar "prop drillimg" (por ejemplo pasar un prop a travez de componentes padres uno y otra vez, aunque no lo usen) y facilitar el uso de recursos en lo lugares donde realmente se necesitan y no hacer recorridos largos pasando un prop.

'UseContext', crea un contexto, el cual es como una "variable" la cual guarda algo, y debemos definir quienes pueden usarla (como el encapsulamiento) y estos componentes la podrán usar. 

Primero creamos el contexto:


import { createContext } from "react";
/* EL contexto
    Primero se crea el contexto, luego
    Crear el provider para proveer el contexto deseado, en este caso el objeto
    Para despues, en este caso, hacer que toda la aplicacion acceda al contexto, ver main.jsx
   
*/

export const FiltroContexto = createContext()
 
export function FiltroProveedor({children}) {
    return (
        <FiltroContexto.Provider value = {{
            categoria: "Todos",
            minPrecio: 0
        }}
        >
            {children}
        </FiltroContexto.Provider>
    )
}
 

como vemos, se crea un componente el cual tiene un 'value' el cual es donde guardaremos lo consultable.

 

Ahora debemos definir quienes lo podrán usar, es el ejemplo le daremos permiso a toda la app (en main.jsx):

 
createRoot(document.getElementById('root')).render(
  <FiltroProveedor>
    <App />
  </FiltroProveedor>,
)


Para consumir el contexto, en un componente autorizado, haremos:


const filtro = useContext(FiltroContexto)
 

PERO, el contexto es estático, no es mutable es perfecto para cosas que no van a cambiar.

Pero si queremos que cambie, debemos hacer esto otro: 


export function FiltroProveedor({children}) { // El proveedor
    const [filtro, setFiltro] = useState({
        categoria: "Todos",
        minPrecio: 0
    })

    return (
        <FiltroContexto.Provider value = {{
            filtro,
            setFiltro
        }}
        >
            {children}
        </FiltroContexto.Provider>
    )
}
 

Cambiamos la función proveedora, agregando un estado y el 'value' con los valores del estado.

[Se mantiene los permisos de uso] 

Y para consumir ahora haremos:


const {filtro, setFiltro} = useContext(FiltroContexto)

Entonces ya podemos cambiar y usar el contexto fácilmente, y se convirtió el contexto en mutable.