useContext

crear Contexto: (Contexto.js)

import { createContext } from "react";

const Contexto=createContext("valor por defecto");
export default Contexto;

Proveer de contexto: (App.js)


import './App.css';
import React from 'react';
import ComPadre from './componentes/ComPadre';
import Contexto from './componentes/Contexto';
function App() {

  return (
    <div className="App">
      <Contexto.Provider value="Hola contexto">
        <ComPadre texto="Hola" />
      </Contexto.Provider>
      
    </div>
  );
}

export default App;

Arbol de componentes: (Compadre,comhijo1,comhijo2)

import ComHijo1 from "./ComHijo1";
function ComPadre({ texto }) {

    return <ComHijo1 texto={texto}/>;
}

export default ComPadre;
import ComHijo2 from "./ComHijo2";
function ComHijo1({ texto }) {

    return <ComHijo2 texto={texto}/>;
}

export default ComHijo1;
import ComHijo3 from "./ComHijo3";
function ComHijo2({ texto }) {

    return <ComHijo3 texto={texto}/>;
}

export default ComHijo2;

Consumir el contexo (ComHijo3)

import { useContext } from "react";
import Contexto from "./Contexto";
function ComHijo3({ texto }) {
    const textoContexto = useContext(Contexto);
    console.log(textoContexto)
    return (<>
        <h1>{texto}</h1>
        <p> Esto viene desde las propiedades por goteo</p>
        <h1>{textoContexto}</h1><p> Esto viene del contexto</p>
    </>)
}

export default ComHijo3;

Ejemplos de useEffect en Calculadora

import React, {useEffect, useState } from 'react';

const Calculadora = () => {
    // Estado para almacenar los datos del formulario
    const [formulario, setFormulario] = useState({
        numero1: 0,
        numero2: 0
    });
    const [suma, setSuma] = useState(0);
    const [multiplicacion, setMultiplicacion] = useState(0);
    useEffect(() => {
        console.log('El componente se ha montado por primera vez');
    }, []); // Array vacío indico que se ejecute una sola vez, al montar (renderizar) el componente
  
    useEffect(() => {
        console.log(formulario);
    }); // Si parámetros se ejecuta cada vez que renderizamos el componente: cuidado con poner cosas que fuercen a enderizar
 
    useEffect(() => {
        console.log('El formulario ha cambiado');
        setSuma(formulario.numero1 + formulario.numero2) // Esto va con retraso
        setMultiplicacion(formulario.numero1 * formulario.numero2) // Esto va con retraso

    }, [formulario]); // Array con propiedades indico que se ejecute cuando cambian esas propiedades
  
    // Función para manejar cambios en los campos de entrada
    const handleInputChange = (event) => {
        const { name, value } = event.target;
        setFormulario({
            ...formulario,
            [name]: Number(value)
        });

   
    };


    return (
        <form >
            <label>
                Numero 1:
                <input
                    type="number"
                    name="numero1"
                    value={formulario.numero1}
                    onChange={handleInputChange}
                />
            </label>
            <label>
                Numero 2:
                <input
                    type="number"
                    name="numero2"
                    value={formulario.numero2}
                    onChange={handleInputChange}
                />
            </label>
            <h1>{formulario.numero1 + formulario.numero2}</h1>
            <h1>{formulario.numero1 * formulario.numero2}</h1>

            <h1>{suma}</h1>
            <h1>{multiplicacion}</h1>
        </form>
    );
};

export default Calculadora;

Solución calculadora

import React, { useState } from 'react';

const Calculadora = () => {
    // Estado para almacenar los datos del formulario
    const [formulario, setFormulario] = useState({
        numero1: 0,
        numero2: 0
    });
    const [suma, setSuma] = useState(0);
    const [multiplicacion, setMultiplicacion] = useState(0);

    // Función para manejar cambios en los campos de entrada
    const handleInputChange = (event) => {
        const { name, value } = event.target;
        setFormulario({
            ...formulario,
            [name]: Number(value)
        });

        setSuma(formulario.numero1 + formulario.numero2) // Esto va con retraso
        setMultiplicacion(formulario.numero1 * formulario.numero2) // Esto va con retraso

    };


    return (
        <form >
            <label>
                Numero 1:
                <input
                    type="number"
                    name="numero1"
                    value={formulario.numero1}
                    onChange={handleInputChange}
                />
            </label>
            <label>
                Numero 2:
                <input
                    type="number"
                    name="numero2"
                    value={formulario.numero2}
                    onChange={handleInputChange}
                />
            </label>
            <h1>{formulario.numero1 + formulario.numero2}</h1>
            <h1>{formulario.numero1 * formulario.numero2}</h1>

            <h1>{suma}</h1>
            <h1>{multiplicacion}</h1>
        </form>
    );
};

export default Calculadora;

Otro ejemplo de renderizar listas

function Alumnos() {
    let lista = [{ id: 1, nombre: "Ana", nota: 7 },
    { id: 2, nombre: "Eva", nota: 5 },
    { id: 3, nombre: "Pep", nota: 8 }
    ]
    return (<ul>
        {
            lista.map((valor) => <li key={valor.id}>{valor.nombre + " : " + valor.nota}</li>)
        }
    </ul>)
}

export default Alumnos;

Ejemplo estados complejos

import React, { useState } from 'react';
import Numero from './Numero'
const Contador = () => {
    // Quiero variables dentro de una página de react tengo que utilizar estado
    const [contador, setContador] = useState({ valor: 0, historial: [] });
    const [cadena, setCadena] = useState("")


    const incrementarContador = () => {
        setContador({ valor: contador.valor + 1, 
                    historial: contador.historial.concat("I") });
        setCadena("")
        console.log(contador)
    };
    const decrementarContador = () => {
        if (contador.valor > 0) {
            setContador({ valor: contador.valor - 1, 
                historial: contador.historial.concat("D") });

        } else {
            setCadena("No puedes poner número negativos")
        }

    };
    const resetearContador = () => {
        setContador({ valor: 0, 
            historial: [...contador.historial,"R"] });
        setCadena("")
    };
    return (
        <div>
            <Numero numero={contador.valor} resetear={resetearContador} />
            <p> {cadena}</p>
            <button onClick={incrementarContador}>Incrementar</button>
            <button onClick={decrementarContador}>Decrementar</button>
            <button onClick={resetearContador}>Reset</button>
        </div>
    );
};
export default Contador;

Interacción estados padres e hijos

import React, { useState } from 'react';
import Numero from './Numero'
const Contador = () => {
    // Quiero variables dentro de una página de react tengo que utilizar estado
    const [contador, setContador] = useState(0);
    const [cadena, setCadena] = useState("")
  
    
    const incrementarContador = () => {
        setContador(contador + 1);
        setCadena("")
    };
    const decrementarContador = () => {
        if (contador>0) {
            setContador(contador - 1);
            
        }else{
            setCadena("No puedes poner número negativos")
        }
        
    };
    const resetearContador = () => {
        setContador(0);
        setCadena("")
    };
    return (
        <div>
            <Numero numero={contador} resetear={resetearContador}/>
            <p> {cadena}</p>
            <button onClick={incrementarContador}>Incrementar</button>
            <button onClick={decrementarContador}>Decrementar</button>
            <button onClick={() => setContador(0)}>Reset</button>
        </div>
    );
};
export default Contador;
import './Numero.css'

function Numero({ numero, resetear }) {
    return <h1 onClick={resetear}>{numero}</h1>
}

export default Numero;

Ejemplo de estados con contador y texto

import React, { useState } from 'react';

const Contador = () => {
    // Quiero variables dentro de una página de react tengo que utilizar estado
    const [contador, setContador] = useState(0);
    const [cadena, setCadena] = useState("")
  
    
    const incrementarContador = () => {
        setContador(contador + 1);
        setCadena("")
    };
    const decrementarContador = () => {
        if (contador>0) {
            setContador(contador - 1);
            
        }else{
            setCadena("No puedes poner número negativos")
        }
        
    };
    return (
        <div>
            <p>Contador: {contador}</p>
            <p> {cadena}</p>
            <button onClick={incrementarContador}>Incrementar</button>
            <button onClick={decrementarContador}>Decrementar</button>
            <button onClick={() => setContador(0)}>Reset</button>
        </div>
    );
};
export default Contador;

Solución 2

import Cabecera from './Cabecera';
import Boton from './Boton';

function Bloque({ texto }) {
    const pinchar=()=>{
        console.log("Has pinchado el botón "+texto)
    }
    // Paso el evento del padre al hijo
    return <div>
        <Cabecera texto={texto} />
        <Boton texto="Pincha aquí" evento={pinchar}/> 
    </div>;
}

export default Bloque;
function Boton({ texto,evento }) {

    return <button onClick={evento}>{texto}</button>;
}

export default Boton;

Solución 1 evento botón

Pasar la información del padre al hijo
En bloque pasamos el texto al botón

import Cabecera from './Cabecera';
import Boton from './Boton';

function Bloque({ texto }) {

    // Paso la información del padre al hijo
    return <div>
        <Cabecera texto={texto} />
        <Boton texto="Pincha aquí" bloque={texto}/> 
    </div>;
}

export default Bloque;
function Boton({ texto,bloque }) {

    return <button onClick={()=>pinchar(bloque)}>{texto}</button>;
}
const pinchar=(texto)=>{
    console.log("Has pinchado el botón "+texto)
}
export default Boton;

Pasar una función como propiedad

App.js

import './App.css'; // Estilos propios del componente 
import Tarjeta from './componentes/Tarjeta'; // Importo la tarjeta

const foo=(elemento)=>{
  console.log("Has pinchado en " + elemento.alt)
    if (elemento.alt === "Marie Curie") {
      elemento.src = "/img/ok.jpg"
    } 
}
function App() {

  // Devuelvo un div con las tarjetas que quiera
  // la Tarjeta tiene unas propiedades que se pasan al componente
  // Pasamos el nombre y la url de la imagen
  return (
    <div className="App">
      <h1>¿Quien descubrió el radio?</h1>
      <Tarjeta nombre="Einstein" correcta="Marie Curie" foo={foo}/>
      <Tarjeta nombre="Marie Curie" correcta="Marie Curie"  foo={foo}/>
      <Tarjeta nombre="Schrodinger" correcta="Marie Curie" foo={foo}/>
    </div>
  );
}

export default App;

Tarjeta.js

import Foto from './Foto'; // Importo Foto
import Cabecera from './Cabecera'; // Importo Cabecera


// Tarjeta le paso las propiedades nombre y url
// Esto va dentro de props pero uso destructuring
function Tarjeta({nombre, correcta,foo}) {
    // En el div es donde pongo la clase, porque es elemento html
    // Uso los componentes Cabecera y Foto
    return (
        <div className="tarjeta">
            <Cabecera  nombre={nombre} correcta={correcta}/>
            <Foto descripcion={nombre}  foo={foo}/>
        </div>
    )
}

export default Tarjeta;

Foto.js

function Foto({descripcion, foo}) {
    let ruta='/img/'
    let nombre=descripcion.toLowerCase().replaceAll(" ","")+".jpg"
    return <img onClick={(evt)=>{foo(evt.target)}} className="foto" src={ruta+nombre} alt={descripcion} />
}

export default Foto;