¡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

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

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

44/45
Recursos

Aportes 35

Preguntas 10

Ordenar por:

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

Deja un ❤️si estas de acuerdo que este curso deberia ser actualizado.

es mala practica hacer uso del async para useEffect como el lo hizo lo mejor es asi :

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Create an scoped async function in the hook
    async function anyNameFunction() {
      await loadContent();
    }
    // Execute the created function directly
    anyNameFunction();
  }, []);```

Si quieren descargar las imagenes que se usan en Platzi conf merch solo tienen que acceder a las urls que vienen en el campo image de initialState.js:

Si estas viendo esto en 2022 y usando la V4 de Strapi:

Para obtener las imagenes en el llamado en la api nadamas tienes que agregar este parametro a la URL:

?populate=%2A

Y todo junto se ve asi:

http://localhost:3006/api/productss?populate=%2A

Fuente: Strapi Docs

Despues de renegar mucho (mucho) (literalmente mas de 6 horas) conseguí hacer deploy en Google Cloud Services siguiendo esta documentación de Strapi:

https://strapi.io/documentation/developer-docs/latest/deployment/google-app-engine.html

Impresionante lo satisfactorio que fue verlo desplegado y funcionando al 100%.
Es un poco complejo hacerlo, pero es gratis! Si les surge alguna duda escribanme al privado y trataré de ayudarlos. Un saludo companeros!

Por si a alguien llegara a tener este error en su consola “Uncaught ReferenceError: regeneratorRuntime is not defined” pueden checar este link

O pueden instalar ‘npm i --save-dev @babel/plugin-transform-runtime’ y dejar asi su archivo .babelrc

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

Como dijo Javier, es mala práctica usar async await en el loop. No sé si React actualizó algo o qué pero mi aplicación se rompió de repente. La corregí así:

// useInitialState.js

  useEffect(() => {
    const getData = async () => {
      const response = await axios(API);
      setProducts(response.data);
    };

    getData();
  }, []);
// useGoogleAdress.js

  useEffect(() => {
    const getData = async () => {
      const response = await axios(API);
      setMap(response.data.results[0].geometry.location);
    };

    getData();
  }, []);

Siento que en Platzi falta un curso de Strapi o de un Headless CMS.

Aquí está la Cloud Function

Que genial herramienta es Strapi!

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

Para hacer la api hacemos

npm create-strapi-app platziconf-backend --quickstart  //Aqui estará nuestra API

Cuando termina nos da un admin, strapi es visual, no es nada de código ya que nos da una interfaz para crear la integración y todo lo que necesita la API.

Si queremos cambiar el puerto en el que se ejecuta podemos cambiarlo entrando a la parte backend del proyecto en la carpeta de config/server.js lo cambiamos a un puerto que se adapte a nuestra configuración.

npm run develop //Para poder visualizarlo

Configuramos el proyecto con nuestro nombre y la configuración que nos pide.

Vamos a content-types builder para crear la colección de productos con los que voy a mostrar en la tienda.

Seleccionamos crear nueva colección y agregamos elementos dependiendo del tipo que sean, por ejemplo: UID (identificador), numéricos, imágenes, texto, etc.

En configuración tenemos los roles que podemos tener, los usuarios que pueden acceder, así como también los permisos que necesitamos.

Vamos a users & permissions plugin / roles ⇒ public para hacer público el recurso. Le vamos a otorgar el permiso de find para poder ver en get los productos y guardamos.

Ahora vamos a nuestras colecciones y agregamos un nuevo producto con los campos que establecimos previamente. Le damos publicar para que este listo y así sucesivamente.

Nos podemos mover a el puerto donde tenemos desplegado el proyecto (la parte del backend) + /products para que nos muestre la api. Pj: localhost:3005/products.

En initialState solo dejamos: cart, buyer, orders.

En useInitialState añadimos la configuración de la API:

import axios from 'axios';

const API= "localhost:3005/products"; //La llamamos

//UseState que se encarga de tener los productos.
const [products, setProducts] = useState([]);

//useEffect para llamar el API y guardar el resultado en los productos.
useEffect(() => {
    const getData = async () => {
      const response = await axios(API);
      setProducts(response.data);
    };

    getData();
  }, []);

return {products,}

Para evitar que la aplicación se rompa en el render inicial vamos a garantizar que esto no pase haciendo una validación en App.jsx:

//Validar si está lleno con información 
const isEmpty = Object.keys(initialState.state).lenght;
//Como el estado es un objeto vamos a validar si tiene elementos

//En el return
<>
{isEmpty > 0 ? (
<AppContext.Provider value={initialState}>
      <BrowserRouter>
        <Layout>
          <Switch>
            {/*switch es el children de layout*/}
            <Route exact path="/" component={Home}></Route>{" "}
            {/*Exacta, con path especifico aquí  es el index y un componente*/}
            <Route exact path="/checkout" component={Checkout}></Route>
            <Route
              exact
              path="/checkout/information"
              component={Information}
            ></Route>
            <Route exact path="/checkout/payment" component={Payment}></Route>
            <Route exact path="/checkout/success" component={Success}></Route>
            <Route component={NotFound}></Route>{" "}
            {/*Ruta 404 cuando sucede un error*/}
          </Switch>
        </Layout>
      </BrowserRouter>
    </AppContext.Provider>
) : <h1>Loading...</h1>}

</>

En products actualizamos:

//Como products ya no está dentro de state, sino que esta en el context.
const { products, addToCart } = useContext(AppContext);

Para poder ver las imágenes vamos a product y modificamos:

<img src={`https://localhost:3006/${product.image[0].url}`}> 

No se si alguno se ha encontado con un error que dice …products.map is not a function. Lo que encontré despues de mucho sufrimiento y frustración es que la respuesta de la API es un poco diferente, por eso la función no se ejecuta correctamente. Al mostrar en consola podemos ver lo siguiente:

Teniendo esto en cuenta, realicé algunos cambios en los llamados a este objeto para poder acceder a los keys que necesitamos. Además, encontré que el formato del link de la API también ha cambiado un poco desde que se lanzó el curso.

Ya con esto, los cambios en el código quedan así:

// useInitialState

// ... 

const useInitialState = () => {
    const [state, setState] = useState(initialState);
    const [products, setProducts] = useState([]);

    useEffect(() => {
        const getData = async () => {
          const response = await axios(API);
          setProducts(response.data.data);
          console.log(response);
        }
        getData();
      }, []);

//...
// products 
  return (
     <div className="Products">
       <div className="Products-items">
          {products.map(product => (
           <Product key={product.uid} product={product} handleAddToCart={ handleAddToCart }/>
         ))} 
       </div>
     </div>
  );
// product
return (
    <div className="Products-item">
       <img src={product.attributes.image.data[0].attributes.name} alt={product.attributes.title} /> 
      <div className="Product-item-info">
        <h2>
          {product.attributes.title}
          <span>
            $
            {' '}
            {product.attributes.price}
          </span>
        </h2>
        <p>{product.attributes.description}</p>
      </div>
      <button type="button" onClick={ handleAddToCart(product) }>Comprar</button>
    </div>
  );

Si se desarrollara para una empresa una tienda, como la que hicimos en este curso, y por nuestra cuenta creamos el backend, ¿habría que desarrollar también un CMS? o ¿Cómo haría el cliente para publicar o dar de baja nuevos productos?

la api no me devuelve los productos 😦

Muy buen curso sí señor, un grande don Oscar!

Si les da error 404 al cargar la página recuerden que el enlace correcto con la nueva versión es:

http://localhost:1337/api/products

Y si les da error 403 (Forbidden) vayan al panel de administrador, a configuración y vayan a “Roles” (hay dos apartados de roles, tenéis que ir al que está debajo de “user & permissions plugin”). Una vez allí pulsen en public y en Product marcad los permisos “find” y “find one”. Guarden los cambios y ya debería funcionar.

Aquí tenéis el link del apartado del rol público si usan el puerto 1337:

http://localhost:1337/admin/settings/users-permissions/roles/2

El enlace a la API que dejó el profe Oscar está caído 😦

No me funciono con la api de Strapi pero si con la fake api del profe 😦

Si a alguien le pasa lo mismo, cuando cambian el puerto que trae por defecto y no les funciona usen npm run build e intente de nuevo.

  1. Otro CMS (a mi me gusta más aunque fue interesante conocer Strapi) es Contenful y es bastate simple de trabajar: https://www.contentful.com/

  2. Les dejo un paquete para crear el loading para React fácilmente: https://www.npmjs.com/package/react-loader-spinner

npx create-strapi-app NAME_APP --quickstart ```

si al ejecutar el comando

npx create-strapi-app conf-backend --quickstart

te da error: You are running Node.js 19.3.0
Strapi requires Node.js >=14.19.1 <=18.x.x

debes desinstalar node e instalar nvm para tener varias versiones de node: https://github.com/coreybutler/nvm-windows/releases
Y en PowerShell ponen nvm install 18.15.0 o la versión que ustedes quieran y después nvm use 18.15.0

Hola
Pueden usar esta API para probar el funcionamiento de la aplicación:

FakeStoreApi

Gente copada, para los que tengan el error de que products.map no es una función. Les dejo la solución que encontré.
https://stackoverflow.com/questions/70816651/array-is-showing-empty-initially-and-i-believe-its-causing-map-is-not-a-func?newreg=b9a26a3484bd4395a2124fdc5ae5dd45

Estaría bueno que mejoraran la calidad de los vídeos. No todos tenemos buena vista.

SI les sale “Uncaught ReferenceError: regeneratorRuntime is not defined” pueden utilizar .then() y .catch()

Bueno esto me tomo tiempo, resulta que a la fecha strapi ha cambiado un poco, Cuando deseen mirar el Json tienen que poner localhost: ‘PUERTO’/api/products, antes de esto recuerden ir a la ruta CONF > COMPLEMENTO DE USUARIOS Y PERMISOS > ROLES > PÚBLICO y marcar la casilla FIND

Uno de los mejores profesores Oscar Barajas Tavares.

OoOOoOO, gracias Oscar, te quiero

Si quieren hacer el deploy de su API en heroku deberan tomar en cuanta algunas cosas.

Lo primero es que SQLite noes es compatible con heroku, por lo que deberan cambiar la base de datos, como Mongo.

Si usan los servidores gratuitos de heroku estos eliminaran cada cierto tiempo las imagenes que almacenadas con strapi. Para evitar esto ultimo debes configurar tu API para almacenar las imagenes en otro lado, yo utilice este plugin de firebase. strapi-provider-upload-to-firebase

Mis queridos Platzibers les comento a los que esten presentando error con el sqlite3 relacionado con node-pre-gyp se soluciona eliminando los node_modules y cambiando la version del sqlite3 de latest por la 5.0.0, no entiendo por que razón no funciona con la latest seria chevere una retroalimentación, en todo caso solo es hacer ese cambio, ejecutar el comando npm install y ¡guala! tenemos nuestro proyecto corriendo ¡saludos!

Los productos (o lo que sea) que metan en la API en desarrollo, no pasa a modo producción, osea que una vez desplegado a producción hay que subir todos los productos de nuevo. En desarrollo suban 2 o 3 productos a modo de prueba y una vez desplegado suben todo, no pierdan tiempo como yo jajaj
Los invito a ver mi repo y mi despliegue
.
https://github.com/Irungaray/Merch-Store
.
https://merchstore-85845.web.app/

No me deja crear una nueva colección y en consola me da el siguiente error ):


[2021-01-27T00:20:14.089Z] error Bootstrap function in plugin "users-permissions" failed
[2021-01-27T00:20:14.091Z] error TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?


Ayudaaaaa

n