¡Bienvenida! Este es un curso especial de React Hooks

1

¿Qué aprenderás en el Curso Profesional de React Hooks?

2

¿Qué son los React Hooks y cómo cambian el desarrollo con React?

Introducción a React Hooks

3

useState: estado en componentes creados como funciones

4

useEffect: olvida el ciclo de vida, ahora piensa en efectos

5

useContext: la fusión de React Hooks y React Context

6

useReducer: como useState, pero más escalable

7

¿Qué es memoization? Programación funcional en JavaScript

8

useMemo: evita cálculos innecesarios en componentes

9

useRef: manejo profesional de inputs y formularios

10

useCallback: evita cálculos innecesarios en funciones

11

Optimización de componentes en React con React.memo

12

Custom hooks: abstracción en la lógica de tus componentes

13

Third Party Custom Hooks de Redux y React Router

Configura un entorno de desarrollo profesional

14

Proyecto: análisis y retos de Platzi Conf Store

15

Git Hooks con Husky

16

Instalación de Webpack y Babel: presets, plugins y loaders

17

Configuración de Webpack 5 y webpack-dev-server

18

Configuración de Webpack 5 con loaders y estilos

19

Loaders de Webpack para Preprocesadores CSS

20

Flujo de desarrollo seguro y consistente con ESLint y Prettier

Estructura y creación de componentes para Platzi Conf Store

21

Arquitectura de vistas y componentes con React Router DOM

22

Maquetación y estilos del home

23

Maquetación y estilos de la lista de productos

24

Maquetación y estilos del formulario de checkout

25

Maquetación y estilos de la información del usuario

26

Maquetación y estilos del flujo de pago

27

Integración de íconos y conexión con React Router

Integración de React Hooks en Platzi Conf Merch

28

Creando nuestro primer custom hook

29

Implementando useContext en Platzi Conf Merch

30

useContext en la página de checkout

31

useRef en la página de checkout

32

Integrando third party custom hooks en Platzi Conf Merch

Configura mapas y pagos con PayPal y Google Maps

33

Paso a paso para conectar tu aplicación con la API de PayPal

34

Integración de pagos con la API de PayPal

35

Completando la integración de pagos con la API de PayPal

36

Paso a paso para conectar tu aplicación con la API de Google Maps

37

Integración de Google Maps en el mapa de checkout

38

Creando un Custom Hook para Google Maps

Estrategias de deployment profesional

39

Continuous integration y continuous delivery con GitHub Actions

40

Compra del dominio y despliega con Cloudflare

Optimización de aplicaciones web con React

41

Integración de React Helmet para mejorar el SEO con meta etiquetas

42

Análisis de performance con Google Lighthouse

43

Convierte tu aplicación de React en PWA

Bonus: trabaja con Strapi CMS para crear tu propia API

44

Crea una API con Strapi CMS y consúmela con React.js

¿Qué sigue en tu carrera profesional?

45

Próximos pasos para especializarte en frontend

Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

19 Días
2 Hrs
54 Min
25 Seg

useContext: la fusión de React Hooks y React Context

5/45
Recursos

Aportes 63

Preguntas 14

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

A mi me gusta trabajar los context de la siguiente manera:

Ya luego el index.js queda solo:

Y para modificarlo sería (estoy usando tailwindcss por lo que solo pondré la lógica acá):

Al tener un botón con el handleClick, cambiará el valor del theme (valor del context), cambiando así las clases. Para los componentes que no tengan action pero que si cambien clases, solo se destructura { theme } = useContext(ThemeContext)

🚨 IMPORTANTE: La llegada de React Hooks y la actualización de React Context NO reemplazan Redux.
👉 Redux NO está muerto, pero tú no lo sabes usar: ¡Larga vida a Redux!


No es mucho pero es trabajo honesto, usando ‘useContext’

En la parte de añadir el color, Oscar no uso {color: color} porque en javascript podemos simplificarlo siempre y cuando el key del object se llame igual a la variable que será su valor.
.

const color = 'red'

const obj = { color }

.
SI fuera el nombre de la variable distinta sería así:

const color2 = 'red'

const obj = { color: color2 }

Yo hice un modo obscuro, que detecta el modo de tu sistema operativo, y lo adapta, recuerda el modo en que dejaste la web la ultima vez que la visitas y obviamente un botón.

Aun es basico, por que me falta mandar el tema seleccionado a los componentes.

Manden feedback

Header.jsx queda asi

import React from "react";

const Header = () => {
  return (
    <div className="Header">
      <h1>ReactHooks</h1>
    </div>
  );
};

export default Header;

ThemeContext.js asi

import React from "react";

export const themes = {
  dark: {
    color: "#4ecca3",
    background: "#232931",
  },
  light: {
    color: "#1e56a0",
    background: "#f5feff",
  },
};

const ThemeContext = React.createContext(themes.dark);

export default ThemeContext;

index.js quité todo

y App.js queda asi

import React, { useState, useEffect } from "react";
import "./App.css";
import Header from "./components/Header";
import Caharacters from "./components/Characters";
import ThemeContext, { themes } from "./context/ThemeContext";

function App() {
  useEffect(() => {
    if (localStorage.getItem("theme") === "dark") {
      darkTheme();
    } else if (localStorage.getItem("theme") === "light") {
      lightTheme();
    } else if (localStorage.getItem("theme") === null) {
      detectColorScheme();
    }
  });

  const [theme, setTheme] = useState(themes.dark);

  const darkTheme = () => {
    setTheme(themes.dark);
    document.documentElement.setAttribute("data-theme", "dark");
    localStorage.setItem("theme", "dark");
  };

  const lightTheme = () => {
    setTheme(themes.light);
    document.documentElement.setAttribute("data-theme", "light");
    localStorage.setItem("theme", "light");
  };

  const detectColorScheme = () => {
    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
      darkTheme();
    } else if (window.matchMedia("(prefers-color-scheme: light)").matches) {
      lightTheme();
    } else {
      darkTheme();
    }
  };

  const handleClick = () => {
    if (theme === themes.light) {
      darkTheme();
    } else if (theme === themes.dark) {
      lightTheme();
    }
    //theme === themes.dark ? setTheme(themes.light) : setTheme(themes.dark);
  };

  return (
    <ThemeContext.Provider value={theme}>
      <div style={theme} className="App">
        <Header />
        <button type="button" onClick={handleClick}>
          Change Color Theme
        </button>
        <Caharacters />
      </div>
    </ThemeContext.Provider>
  );
}

export default App;

Esta forma ya lo había echo con javascript canilla, ahora quiero adaptarlo totalmente a React 💪🏻⚛

Hola aqui coloco mi solucion y el paso a paso del porque

  1. debido a que aprendimos useContext ahroa podemos compartir informacion entre componentes, La informacion que vamos a compartir en este caso sera el estado que creamos anteriormente, esdecir quitamos el estado darkMode del componente Header y lo ponemos en App. cabe aclarar que los componentes que esten encerrados en <ThemeContext.Provider> son los unicos que veran el estado que se compartira, debido a eso puse <ThemeContext.Provider> en app.js, para que se pueda compartir entre el componente App y Header
import './App.css';
import Header from './components/Header';
import Characters from './components/Characters';
import ThemeContext from './context/ThemeContext';
import React, { useState, useContext } from 'react'



function App() {

  
  const [darkMode, setDarkMode] = useState(false)

  return (
    <ThemeContext.Provider value={{darkMode, setDarkMode}}>
      <div className={darkMode? "Dark": "Light"}>
        <h1>hola pescado</h1>
        <Header></Header>
        <Characters></Characters>
      </div>
    </ThemeContext.Provider>
  );
}

export default App;

  1. ahora que el componente app y header pueden observar el estado, y anteriormente ya habiamos programado que el cambio de estado lo hiciera Header al dar clic. entonces no debemos cambiar nada en este componente, solo debemos poner el hook useContext para poder manipular el estado desde aqui y quitar el estado declarado, ya que lo pusimos en App.js
import React, { useState, useContext } from 'react'
import ThemeContext from '../context/ThemeContext';

export default function Header() {
    
    const {darkMode, setDarkMode} = useContext(ThemeContext);
    const handleClick = () => {
        setDarkMode(!darkMode);
    }

    return (
        <div className="Header" >
            <h1 >React Hooks</h1>
            <button type="button" onClick={handleClick}>{darkMode ? 'Dark Mode' : 'Light Mode'}</button>

        </div>
    )
}

3)La manera en la que cambie el background fue con un condicional al momento de nombrar la clase: si darkMode es true entonces llama a la clase Light y si darkMode es false llama a la clase Dark, estas clases se crearon en app.css

<div className={darkMode? "Light": "Dark"}>
.Dark{
  background-color: darkblue;
}

.Light{
  background-color: white;
}

Para el Profesor es sencillo de entender, sin embargo yo debo hacer un énfasis para quién no lo entendiói a la primera, me pasó a mí:

  • Objetivo: Se debe crear un Contexto del cuál se van a traer datos, o la información del contexto, para que algún componente lo consuma.

    En lenguaje más humano, imagina que es un restaurante móvil que puedes conectar a la ventana de tu casa para que te prepare y entregue lo que ahí dentro se puede pedir, consultar, consumir.
    .
  • 1 - Se debe crear un Contexto de dónde poder obtener esa información.

/// ThemeContext.js

import React from 'react'

const ThemeContext = React.createContext(null);

export default ThemeContext;
  • 2 - Definir la ubicación del Provider para que todo el App pueda acceder a la información sin importar el nivel.
  • 3 - ‘Definir la carta del restaurante’: Definir la data que va a entregar el Provider dentro del contexto.
    /// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import ThemeContext from './context/ThemeContext';

const COLOR_MODE = {
  darkColorMode: 'dark-mode',
  lightColorMode: 'light-mode',
};

ReactDOM.render(
  <React.StrictMode>
    <ThemeContext.Provider value={COLOR_MODE}>
      <App />
    </ThemeContext.Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

El parámetro value es en donde vamos a colocar la información que será consumida.

  • Existe un Provider y un Consumer . Estos dos van a entregar y consumir, respectivamente, la información que habita en el contexto, dependiendo de la necesidad.
    Nota: Se recomienda que el Provider sea el componente de más alto nivel dentro del App.
    .
  • 4 - Conectar la información del Provider (contexto) con el componente.
  • 5 - Consumir.
///  App.js
import React, { useContext, useState } from 'react';
import Header from './components/Header';
import Characters from './components/Characters';
import ThemeContext from './context/ThemeContext';
import './App.css';

function App() {
  const [darkMode, setDarkMode] = useState(false);
  const {darkColorMode, lightColorMode} = useContext(ThemeContext);
  
  const handleClick = () => {
    setDarkMode(!darkMode);
  }
    
  return (
    <div className={`App ${darkMode ? darkColorMode : lightColorMode}`}>
      
      <Header />

      <div>
        <button type="button" onClick={handleClick}>
          { darkMode ? 'Change to LightMode' : 'Change to DarkMode' }
        </button>
      </div>

      <Characters />

    </div>
  );
}

export default App;
///  Header.js
import React, {useContext} from 'react'
import ThemeContext from '../context/ThemeContext'

const Header = () => {
    const {titleColor} = useContext(ThemeContext);
    console.log(titleColor)
    
    return (
        <div className="Header">
            <h1 >React Hooks</h1>
        </div>
    )
}

export default Header

Espero los pueda ayudar!

Apuntes

  • Conecta todos tus componentes de una manera fácil con React
  • Nos ayuda pasar la información entre componentes
  • Conectar sin necesidad de pasar props y no estar ligados a pasar la información de padre a hijo

Ejemplo

import React from 'react'

const ThemeContext = React.createContext(null);
// Nos Devuelve un Provider que luego lo podemos
// usar para envolver nuestra aplicación

export default ThemeContext;

Usando el Provider:

import React from 'react';
import ReactDOM from 'react-dom';
import ThemeContext from './context/ThemeContext';

ReactDOM.render(
  <React.StrictMode>
    <ThemeContext.Provider value="blue">
      {/*Mi Aplicación*/}
    </ThemeContext.Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
  • Este formato nos permite tener toda una lógica establecida con configuraciones que podemos transmitir a nuestra aplicación
  • Se podría usar para tener todo un estado y compartirlo por todos los lugares según sea el caso y activarlo según el componente que nosotros necesitemos
    • Debido a que estamos pasando el valor en nuestro Provider
    • Logrando que nuestro contexto use esta información para recibir esta información y poderlo presentar a lo largo de nuestra aplicación

Dos sugerencias al momento que uses useContext

  1. Un error muy comun es hacerlo globalmente disponible para todos tus componentes de tu aplicacion, cuando realmente solo es necesario para una parte de tu aplicacion. Tener el value del contexto en scope en el area donde solo se necesita va a mejorar el performance y el mantenimiento.

  2. Que pasaria si alguien consume tu context value sin usar el Context Provider? El error que te muestra React, no ayuda mucho. Por eso siempre es bueno validar si existe el context, y tambien crear un custom hook del Context que uses, en este caso seria algo asi:

function useTheme() {
  const context = React.useContext(ThemeContext)
  if (!context) {
    throw new Error('useCount must be used within a CountProvider')
  }
  return context
}

Y este custom hook lo usas en los componentes donde necesites ese Theme Context.

Un amigo me mostro otra forma de consumir el context y me parecio super practica esta forma:
Basicamente creas un hook y al exportar el contexto retornar una funcion que ya consume por asi decirlo el context en si. De esta forma te evitas estar nombrando en todos lados useContext(elContexto)

Aca como queda el index:

Como consumirlo:

![](

Yo creo que la carpeta context más bien debería llamarse provider/s y tu ThemeContext -> ThemeProvider para así exportarlo como un componente (provider) que recibe hijos, de esta manera el código queda más claro y limpio

<h3>Otra forma de usar useContext</h3>

En lo personal me gusta usar useContext de la siguiente manera

Context.js

import React, { createContext } from "react";

const ThemeContext = createContext();

export const ContextProvider = ({ children }) => {
  // Aca defines toda tu logica.

  const color = "red";

  return (
    <ThemeContext.Provider value={{ color }}>{children}</ThemeContext.Provider>
  );
};

export default ThemeContext;

index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import { ContextProvider } from "./Context";

ReactDOM.render(
  <React.StrictMode>
    <ContextProvider>
      <App />
    </ContextProvider>
  </React.StrictMode>,
  document.

Luego para acceder alguna propiedad que hayas definido en tu context solo tienes que hacer:

import React, { useContext } from "react";
import "./App.css";
import ThemeContext from "./Context";

function App() {
  const { color } = useContext(ThemeContext);

  return (
    <div>
      <h1 style={{ color }}>Hola mundo</h1>
    </div>
  );
}

export default App;

En mi caso, yo acostumbro a exportar de una vez el useContext en el archivo donde se crea el contexto. Quedaría algo así:

import { createContext, useContext } from 'react';

export const ThemeContext = createContext(null);

export function useTheme() {
  return useContext(ThemeContext);
}

Posteriormente, en el componente, solo debo importar useTheme y usarlo directamente:

import React,{useState} from 'react';
import {useTheme} from 'context/theme'

const Header = () => {
    const [darkMode,setDarkMode] = useState(false)
    const color=useTheme()
	.........

Les dejo el link de mi repositorio, hecho en Nextjs:
https://github.com/danyel117/platzi-conf-store

Si también quedaste con la duda de porqué se usa la palabra Context.Provider les dejo una lectura que me lo aclaró muchísimo.
Creo que también es importante complementar para saber que esta funcionalidad también se puede hacer con componentes de clase, por ejemplo.

comparto mi solución que aprendí del master Jonathan MirCha para hacer un dark mode aprovechando el verdadero potencial del useContext.

ThemeContext

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

// Me creo un contexto:
const ThemeContext = createContext();
// creo un estado inicial para mi estado:
const initialDarkMode = false;
// Aqui mismo creo mi provider con el paramtro children tipo
// arrow function
const ThemeProvider = ({ children }) => {
   //Creo un estado y le defino mi estado inicial del tema
   const [darkMode, setDarkMode] = useState(initialDarkMode);

   // manejador para setear el estado:
   const handleDakMode = () => setDarkMode(!darkMode);
   // los datos que voy a proveer a mis compoenntes children
   const data = { darkMode, handleDakMode };
   
   // Retorno mi contexto listo para proveer a sus componentes hijos o children.
   return (
      <ThemeContext.Provider value={data}>{children}</ThemeContext.Provider>
   )

}
// exporto mi provedor 
export { ThemeProvider };
// exporto mi 
export default ThemeContext;

index

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import ThemeContext, { ThemeProvider } from './context/ThemeContext';



const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(

  <React.StrictMode>
    {/* Lammo a mi proveedor ThemeProvider para envolver mi App */}
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

App

import { useContext } from 'react';
import './App.css';
import Characters from './components/Characters';
import Header from './components/Header';
import ThemeContext from './context/ThemeContext';

function App() {
  const { darkMode } = useContext(ThemeContext);

  return (
    // Creo un operador tenario dentro de un template literal ` ${}`
    <div className={`App ${darkMode ? "dark" : "light"}`}>
      <Header />
      <Characters />
      <h1>Hola mundo</h1>
    </div>
  );
}

export default App;

Header

import React, { useContext, useState } from 'react'
import ThemeContext from '../context/ThemeContext';

const Header = () => {
   // destructuro mi estado y funcion de manejo del estado de mi contexto
   const { darkMode, handleDakMode } = useContext(ThemeContext);
   return (
      <div className='header'>
         <h1>ReactHooks</h1>
         {/* a cada boton le comparto mi funcion seteadora */}
         <button type='button' onClick={handleDakMode}>{darkMode ? 'Dark Mode' : 'Light Mode'}</button>
         <button type='button' onClick={handleDakMode}>{darkMode ? 'Dark Mode' : 'Light Mode'}</button>
      </div>
   )
}

export default Header

Hola a todos, mi aporte es algo muy parecido a lo que publico @Antonio Jolse Hernandez Medina pero con unas pequeñas variaciones.

Lo primero es crear en la carpeta Context nuestro archivo ThemeContext.js con el siguiente código:

import { createContext, useState } from 'react';
const ThemeContext = createContext();

const ThemeProvider = ({children}) => {

  const [theme, setTheme] = useState("red");
  return (
    <ThemeContext.Provider value={{
        theme,
        setTheme
      }
    }>
      {children}
    </ThemeContext.Provider>
  )
}

export { ThemeContext };
export default ThemeProvider;

Después de esto buscamos en donde queremos envolver nuestros componentes con este context y hacemos lo siguiente (para nuestro caso lo vamos hacer en el archivo index.js ya que queremos que este componente envuelva a todos los demás componentes):

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import ThemeProvider from './context/ThemeContext';

ReactDOM.render(
  <React.StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Ya con la configuración lista del context y envolviendo nuestros componentes dentro de nuestro context, generamos un hook personalizado en el cual se va a encargar de devolver los valores de nuestro context(Propiedades y métodos). para ello creamos una carpeta llamada hooks y dentro de ella creamos un archivo llamado useTheme.js con el siguiente código:

import { useContext } from 'react';
import { ThemeContext } from '../context/ThemeContext';

const useTheme = () => {
  return useContext(ThemeContext);
}

export default useTheme;

Con este código nos estamos evitando tener que repetir la siguiente línea de código además del import de useContext en todos los componentes en donde necesitemos obtener los valores del contexto.

import { useContext } from 'react';
import { ThemeContext } from '../context/ThemeContext';
useContext(ThemeContext);

Ye teniendo el archivo useTheme.js configurado solo resta utilizarlo en todos los componentes donde necesitemos obtener los valores de este contexto como muestra la siguiente línea de código:

import useTheme from '../hooks/useTheme';
const { theme } = useTheme();

NOTA: Como pueden observar aquí hacemos una desestructuración de los valores de nuestro contexto, que para el caso solo utilizamos theme, pero si quisiéramos utilizar los demás valores como setTeheme, solo es agregarlos a la desestructuración.

Para nuestro caso lo vamos a utilizar en el componente Header como se muestra a continuación.

mport { useState } from 'react'
import useTheme from '../hooks/useTheme';

const Header = () => {
  
  const [darkMode, setDarkMode] = useState(false);

  const handleClick = () => {
    setDarkMode(!darkMode);
  }

  const { theme } = useTheme();

  return (
    <div className="heder">
      <h1 style={{color: theme}}>React Hooks</h1>
      <button type="button" onClick={handleClick}>
        {
          darkMode ? "Ligth Mode" : "Dark Mode"
        }
      </button>
      <button type="button" onClick={() => { setDarkMode(!darkMode) }}>
        {
          darkMode ? "Ligth Mode 2" : "Dark Mode 2"
        }
      </button>
    </div>
  );
}
 
export default Header

Y eso es todo lo que tendríamos que realizar para configurar nuestro contexto espero les sirva de mucha ayuda. Cabe aclarar que se podría evitar realizar el paso de crear el hook personalizado, creo que ya son gustos y formas de programar y aunque solo son un par de líneas de código que solo te evitarías repetir, cuando ya lo utilizas en muchos componentes es donde realmente ves que te estas evitando repetir el mismo código siempre.

Mi proyecto hasta ahora:

No puedo usar un useState en un provider?, me esta tirando error por eso pregunto

Context

import React, { useState } from 'react';

const initialState = 'light';

const ThemeContexProvider = ({ children }) => {
  const [theme, setTheme] = useState(initialState);
  return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
};

export default ThemeContexProvider;
export const ThemeContext = React.createContext(initialState);

Header

import React, { useContext } from 'react';

import { ThemeContext } from '../context/ThemeContext';

const Header = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <div className={`flex flex-col items-center pb-5 md:pb-3 bg-${theme}-100 text-${theme}-200`}>
      <h1 className="text-5xl font-bold py-4">React Hooks!!!</h1>
      <div className="flex flex-row">
        <button
          className="focus:outline-none border-2 border-gray-900 rounded-md px-4 py-2 mr-2 bg-gray-800 text-gray-50"
          onClick={() => setTheme('dark')}
        >
          Dark Mode
        </button>
        <button
          className="focus:outline-none border-2 border-gray-900 rounded-md px-4 py-2 bg-gray-300 text-gray-900"
          onClick={() => setTheme('light')}
        >
          Light Mode
        </button>
      </div>
    </div>
  );
};

export default Header;```

Usando el ejemplo de Antonio José Hernández Medina, que esta muy interensante, combinado con la idea de Oscar Barajas, me ha quedado un experimiento donde uso el contexto para cambiar el borde de color y el levantamiento de estado y los estados para el modo luz o oscuro

Dentro de los enlaces de lecturas recomendadas, seria bueno actualizar el del tutorial, ya que esta documentado con componentes de clase, seria mejor si se actualizara ya con hooks como tal …

de mi parte tambien usado RxJS para la comunicacion entre compoenentes

bueno el curso pero como ya está desactualizazo, de este video no me ha funcionado nada, alguien que pueda orientarme le estaría profundamente agradecido.

Por favor, profesor, haz el curso de inglés de Platzi
te vendría muy bien hacerlo, sobre todo por la pronunciación

exelente


Reto cumplido. Aun me cuesta trabajar de forma mas ágil el useContext así que me ayude un poco de algunos videos y aportes de los compañeros.

  • ThemeContext.js

  • App.js

  • Header.jsx

No entiendo porque usar así el context, la mejor forma y pienso yo que aportaría mas al curso es usar el context para envolver un estado que pueda ser seteado para el tema en vez de pasar solo un string como color. Creo yo que estamos aprendiendo un curso profesional y esto no le veo nada profesional mas bien es como lo básico.

Yo lo hice de forma que tengamos los styles en el mismo ThemeContext.js y solo intercambiarlos en <App> y en Header solo cambiar el estado para cambiar estilos

Se envuelve App con el Theme provider, para que este pueda ser consumido en toda la aplicacion

En app se utilizan el metodo selectTheme() que te retorna el dark theme si es true y el light theme si es false

Y en Header se cambia el estado del change theme para que cambie entre true y false

La verdad yo prefiero cambiar los estilos cambiando el ClassName pero esta tambien es una forma de realizarlo, espero y les sirva 😃

Me tome la libertad de hacer media query para adaptarlo a pantallas.



Código

Aquí puede revisar mas a fondo useContext:
https://youtu.be/5LrDIWkK_Bc


![](

useContext es una herramienta poderosa y muy facil de usar, lo que no me queda del todo claro es cuando es mejor utilizarla

Para ampliar más del tema también les comparto este video
useContext

Les comparto este videotutorial donde se explica un poco más a profundidad lo que puede lograrse con useContext https://www.youtube.com/watch?v=lSMBhUEVK8k

  • context permite poder pasar valores entre componentes sin tener que hacerlo por props
  • Al usar createContext el valor por defecto que le pasamos solo es usado únicamente si no hay un Provider.
    Nota: pasar undefined como valor al Provider no hace que los componentes que lo consumen utilicen defaultValue

Gracias al aporte de un compañero conseguí montar el context para ejecutar el cambio de modo Dark a Light

Hola! Yo lo hice de la siguiente manera, en el archivo de ThemeContext creé el contexto ‘ThemeContext’, además creé una función llamada ThemeProvider, que retorna el provider con el valor que se quiere retornar. Y por último cree mi propio hook de useTheme, que hace uso del contexto de ‘ThemeContext’ y retorna el valor previamente asignado en el ThemeProvider. De la siguiente manera:

Siento que es mejor tenerlo de esta forma, porque luego en el index, solamente necesito encapsular el componente de APP con la función de ‘ThemeProvider’, de la siguiente manera:

Ahorita el value del provider es estatico, solamente retorna la palabra ‘green’, pero suponiendo que el value es un objeto con funciones y más atributos, se puede escribir toda esa lógica dentro del método ‘ThemeProvider’ y quedaría mejor.

Por último, luego de encapsular el componente App con ‘ThemeProvider’, ya toda la app tiene acceso a este contexto, y recordando que creamos nuestro propio hook de ‘useTheme’, ya dicho método, hace uso del metodo ‘useContext’ y retorna el valor del contexto, por lo tanto, si queremos utilizar el contexto en otro componente, solamente es necesario importar el hook de ‘useTheme’, de la siguiente manera:

import React, { createContext, useState } from "react";

export const theme = {
  dark: {
    background: "black",
    color: "white"
  },
  light: {
    background: "white",
    color: "black"
  }
};

export const ThemeContext = createContext();

export const ContextProvider = (props) => {
  const [stateTheme, setTheme] = useState(false);
  const value = { stateTheme, setTheme, theme };

  return <ThemeContext.Provider value={value} {...props} />;
};
> > 


Cambiando el modo, de oscuro a normal y viceversa, usando useContext

// ThemeContext.js
import React from "react";

const toggleDarkModel = () => {};

const theme = {
	darkModeActive: false,
	toggleDarkModel,
};

const ThemeContext = React.createContext(theme);

export default ThemeContext;
// App.js
import React, { useState } from "react";

import "./App.css";
import ThemeContext from "./context/ThemeContext";
import Header from "./components/Header";
import Cryptos from "./components/Cryptos";

let mode = false;
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
	mode = true;
}

function App() {
	const [darkModeActive, setDarkModeActive] = useState(mode);
	const toggleDarkModel = () => {
		setDarkModeActive(!darkModeActive);
	};
	return (
		<ThemeContext.Provider value={{ toggleDarkModel, darkModeActive }}>
			<div className={`App ${darkModeActive ? "dark-mode" : "light-mode"}`}>
				<section className="section">
					<Header />
					<div className="container is-flex is-flex-direction-row is-align-content-center is-justify-content-center is-flex-wrap-wrap">
						<Cryptos />
					</div>
				</section>
			</div>
		</ThemeContext.Provider>
	);
}

export default App;
// Header.jsx
import React, { useContext } from "react";
import ThemeContext from "../context/ThemeContext";

const Header = () => {
    const { toggleDarkModel, darkModeActive } = useContext(ThemeContext);
    return (
        <div className="Header container">
            <h1 className="title">Crypto Swag</h1>
            <button onClick={toggleDarkModel} className={`button is-small ${darkModeActive ? "is-white" : "is-dark"}`}>
                <span className="icon is-small">
                    <i className={`mdi ${darkModeActive ? "mdi-lightbulb-on" : "mdi-lightbulb-off"}`}></i>
                </span>
            </button>
        </div>
    );
};

export default Header;

Asi va mi proyecto con un poco de diseño y algunas mejoras en cuanto a el funcionamiento. Para aprender tambien hay que practicar!!!

![](

Bueno haciendo la tarea
DarkMode

LigthMode

Me esta gustando este ejercicio esta quedando excelente

Yo encontré esta forma de usar combinados el useState y useContext para poder actualizar el DarkMode.
En el App.jsx importe el ThemeContext y envolví la App pasando como value un estado establecido con useState y una función que actualiza ese estado:

import React, { useState } from 'react';
import Header from './components/Header';
import Characters from './components/Characters';
import ThemeContext from './context/ThemeContext';

function App() {
  const [theme, updateTheme] = useState('light-mode');
  function setTheme(newTheme) {
    updateTheme(newTheme);
  }
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <div className="App">
        <Header />
        <Characters />
      </div>
    </ThemeContext.Provider>
  );
}

export default App;

Después en el Header.jsx traje el context y quedó de esta manera:

import React, { useState, useContext } from 'react';
import ThemeContext from '../context/ThemeContext';

const Header = () => {
  const [darkMode, setDarkMode] = useState(false);
  const { theme, setTheme } = useContext(ThemeContext);
  const handleClick = () => {
    if (theme === 'light-mode') {
      setTheme('dark-mode');
      document.querySelector('body').classList.add('dark-mode');
    } else {
      setTheme('light-mode');
      document.querySelector('body').classList.remove('dark-mode');
    }
    setDarkMode(!darkMode);
  };
  return (
    <div className="Header row">
      <h1>StarWars Characters API</h1>
      <button className="DarkModeButton" type="button" onClick={handleClick}>
        {darkMode ? 'Light Mode' : 'Dark Mode'}
      </button>
    </div>
  );
};

export default Header;

Aquí les dejo mi reto!

Pude lograr el reto pasado con esta clase. Les comparto mi código.

App.jsx

Hader.jsx

css

.lightmode {
  background-color: beige;
}

.darkmode {
  background-color: midnightblue;
  color: white;
}
import React, { useState } from 'react';

const ThemeContext = React.createContext({ isDark: null, toggleTheme: () => null });

const CACHE_KEY = 'IS_DARK';

const ThemeContextProvider = ({ children }) => {
    const [isDark, setIsDark] = useState(() => {
        const isDarkUserSetting = localStorage.getItem(CACHE_KEY)
        return isDarkUserSetting ? JSON.parse(isDarkUserSetting) : false
    })

    const toggleTheme = () => {
        setIsDark((prevState) => {
            localStorage.setItem(CACHE_KEY, JSON.stringify(!prevState));
            return !prevState;
        })
    }

    return (
        <ThemeContext.Provider value={{ isDark, toggleTheme }}>
            { children }
        </ThemeContext.Provider>
    )

}

export { ThemeContext, ThemeContextProvider };```

ThemeContext.j

import React, { createContext, useState  } from "react";
import styled from 'styled-components';

const ThemeContext = createContext({});

export const Card = styled.div`
 background-color: ${props => props.dark ? '#8C71B0' : 'papayawhip'};
 color:  ${props => props.dark ? '#202020' : 'palevioletred'};
`;

export function ThemeContextProvider({children}){
    const [darkMode, SetDarkMode] = useState(false);

    return (
        <ThemeContext.Provider value={{darkMode, SetDarkMode}}>
            {children}
        </ThemeContext.Provider>
    );
}

export default ThemeContext;```

Hice un tutorial de como usar React Context y Local Storage al mismo tiempo ve a verlo

Al igual que algunos compañeros cambie de lugar el provider, y use el hook de useState para cambiar el provider.

Pueden revisar el código desde mi github https://github.com/zurita-dev/React-Hooks/tree/useContext

¿Alguien sabe porque no funciona el Context en el primer render en produccción? Lancé una app en gatsby, de ejemplo, usé context para el dark-mode (como default) pero lo toma como undefined en el primer render

los hooks, podrian reemplazar la funcionalidad de redux?

Yo lo hice de esta forma :

Yo lo hice de esta manera :

Me tomó algo de rato procesar lo que estaba haciendo pero reto completado

Entonces la diferenca de Redux y useContext es que con este ultimo puedes crear varios “Store” como source???