隆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

Integraci贸n de pagos con la API de PayPal

34/45
Recursos

Aportes 35

Preguntas 9

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Bot贸n paypal 2021 react 17.x.x

npm i react-paypal-button-v2

Para que se les abra en el navegador la documentaci贸n de cualquier paquete:

npm docs <nombre-paquete>

npm docs react-paypal-button

Archivo nuevo src/utils/index.js

export const handleSumTotal = (cart) => {
  const reducer = (acc, cur) => acc + cur.price;
  const sum = cart.reduce(reducer, 0);
  return sum;
}

La libreria de react-paypal-button esta depreciada segun su documentacion yo use @paypal/react-paypal-js

Se importa un PayPalScriptProvider y se le pada un parametri option client-id que es el client id que se encuetra en el la app que creamos en paypal

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Home } from '../containers/Home';
import { Checkout } from '../containers/Checkout';
import Information from '../containers/Information';
import Payment from '../containers/Payment';
import Success from '../containers/Success';
import NotFound from '../containers/NotFound';
import '../styles/components/App.css';
import Layout from '../components/Layout';
import useInitialState from '../hooks/useInitialState';
import AppContext from '../context/AppContext';
import { PayPalScriptProvider } from '@paypal/react-paypal-js';

function App() {
  const initialState = useInitialState();
  return (
    <PayPalScriptProvider options={{"client-id": "AQ348XIPD92Fd586HLuYrTc1tqaYZHEpZIeT3rlMH04KUQBjZSZ0G2H4m4vsIhXs2-j3tSjtBbpcW-Ma"}}>
      <AppContext.Provider value={initialState}>
        <BrowserRouter>
          <Layout>
            <Routes>
              <Route exact path="/" element={<Home />} />
              <Route exact path="/checkout" element={<Checkout />} />
              <Route
                exact
                path="/checkout/information"
                element={<Information />}
              />
              <Route exact path="/checkout/payment" element={<Payment />} />
              <Route exact path="/checkout/success" element={<Success />} />
              <Route element={<NotFound />} />
            </Routes>
          </Layout>
        </BrowserRouter>
      </AppContext.Provider>
    </PayPalScriptProvider>
  );
}

export default App;

despues en el payment tenemos esta vista que redirige a succes

import React, { useContext , useState} from 'react';
import AppContext from '../context/AppContext';
import { Link, useNavigate } from 'react-router-dom';
import '../styles/components/Payment.css';
import { handleSumTotal } from '../utils';
import { PayPalButtons } from '@paypal/react-paypal-js';
const Payment = () => {
  const {
    state: { cart },
  } = useContext(AppContext);
  const [paidFor , setPaidFor] = useState(false)

  const handleApprove = (orderID) => {
    setPaidFor(true)
  }

  const history = useNavigate()
  if(paidFor)
  {
    history('/checkout/success')
  }
  return (
    <div className="Payment">
      <div className="Payment-content">
        <h3>Resumen del pedido:</h3>
        {cart.map((product, index) => (
          <div key={index} className="Payment-item">
            <div className="Payment-element">
              <h4>{product.title}</h4>
              <span>{product.price}</span>
            </div>
          </div>
        ))}
        {cart.length > 0 ? (
            <h3>{`Total: ${handleSumTotal(cart)}`}</h3>
          ) : <></> }
        <div className="Payment-button" id="payment-button-container">
          <PayPalButtons
                createOrder={(data, actions) => {
                    return actions.order.create({
                        purchase_units: [
                            {
                                amount: {
                                    value: handleSumTotal(cart),
                                },
                            },
                        ],
                    });
                }}
                onApprove={(data, actions) => {
                    return actions.order.capture().then((details) => {
                        const name = details.payer.name.given_name;
                        handleApprove(data.orderID)
                    });
                }}
            />
        </div>
      </div>
      <div />
    </div>
  );
};

export default Payment;

Los tipos para typescript:

type PayPalButtonProps = {
  paypalOptions: PaypalOptions;
  buttonStyles: ButtonStylingOptions;
  amount: number;
  subscriptionPlanId?: string;
  onApprove?: (data, authId) => void;
  onPaymentStart?: () => void;
  onPaymentSuccess?: (response: OnCaptureData) => void;
  onPaymentError?: (msg: string) => void;
  onPaymentCancel?: (data: OnCancelData) => void;
  onShippingChange?: (data: OnShippingChangeData) => 
    Promise<void | string | number> |
    string |
    number |
    void;
}

Osea que solo yo est谩 tomando este curso? Todos los comentarios son de hace un a帽o, dos a帽os, tres a帽os鈥 POR DIOS!

ESTUDIANTES 2023, les recomiendo esta docu

package/@paypal/react-paypal-js

Luego dejo mi c贸digo adjunto.

Comando

npm i react-paypal-button-v2 

archivo Payment.jsx

import React, { useContext } from 'react';
import { PayPalButton } from 'react-paypal-button-v2';
import AppContext from '../context/AppContext';
import '../styles/components/Payment.css';

const Payment = ({ history }) => {
  const { state, addNewOrder } = useContext(AppContext);
  const { cart, buyer } = state;

  const paypalOptions = {
    clientId: 'ATN4MgsCVKSXinkSTL1YqlANTikW5fXyo5C7TkyVUG7JB0DTr1G2aabkWFF9Uz6kKo61tL48cfWpomc4',
    intent: 'capture',
    currency: 'USD',
  };

  const buttonStyles = {
    layout: 'vertical',
    shape: 'rect',
  };

  const handlePaymentSuccess = (data) => {
    console.log(data);
    if (data.status === 'COMPLETED') {
      const newOrder = {
        buyer,
        product: cart,
        payment: data,
      };
      addNewOrder(newOrder);
      history.push('/checkout/success');
    }
  };

  const handleSumTotal = () => {
    const reducer = (accumulator, currentValue) => accumulator + currentValue.price;
    const sum = cart.reduce(reducer, 0);
    return sum;
  };

  return (
    <div className='Payment'>
      <div className='Payment-content'>
        <h3>Resument del pedido:</h3>
        {cart.map((item) => (
          <div className='Payment-item' key={item.title}>
            <div className='Payment-element'>
              <h4>{item.title}</h4>
              <span>
                $
                {' '}
                {item.price}
              </span>
            </div>
          </div>
        ))}
        <div className='Payment-button'>
          <PayPalButton
            paypalOptions={paypalOptions}
            buttonStyles={buttonStyles}
            amount={handleSumTotal()}
            onPaymentStart={() => console.log('Start Payment')}
            onPaymentSuccess={(data) => handlePaymentSuccess(data)}
            onPaymentError={(error) => console.log(error)}
            onPaymentCancel={(data) => console.log(data)}
          />
        </div>
      </div>
      <div />
    </div>
  );
};

export default Payment;

Me sale este error de dependencia y no encuentro como solucionarlo sin instalar otra versi贸n de react:

Wow alguien m谩s siente que el video fue un poco largo 馃槢 Necesario pero largo

Para las personas que tienen problemas con el btn de Paypal aqui les dejo una soluci贸n:

npm i @paypal/react-paypal-js

<code> 

import React from 'react'
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";

const PaypalPay = () => {
  return (
    <PayPalScriptProvider
      options={{
        "client-id": process.env.REACT_APP_PAYPAL_ID,
        currency: "USD",
      }}>

<PayPalButtons
        style={{ layout: "vertical" }}
        disabled={false}
        createOrder={(data, actions) =>
          actions.order
            .create({
              purchase_units: [
                {
                  amount: {
                    value: Number.parseFloat(handleSumTotal()).toFixed(2),
                  },
                },
              ],
            })
            .then((orderId) => {
              return orderId;
            })
        }
        onApprove={(data, actions) => {
          return actions.order
            .capture()
            .then((data) => {
              // Your code here after capture the
              paymentHandleSuccess(data);
            })
            .catch((error) => console.log(error));
        }}
      />
    </PayPalScriptProvider>

  )
}

export default PaypalPay


 


Esta clase deberian de actualizar.

Pesima clase !

Despues de mucho renegar llegu茅 a la misma soluci贸n que Hector:

const handleSumTotal = (cart) => {
  const reducer = (accumulator, currentValue) =>
    accumulator + currentValue.price;
  const sum = cart.reduce(reducer, 0);

  return sum;
};

export default handleSumTotal;

Y la invoco en Checkout, Information y Payment pas谩ndole cart como par谩metro:

<h3>{`Total Price: $${handleSumTotal(cart)}`}</h3>

Recordemos que (si no me equivoco) cart viene del estado, que viene del contexto. As铆 est谩 en Checkout.jsx:

  const { state, removeFromCart } = useContext(AppContext);
  const { cart } = state;

Ojal谩 les sirva!

En dos a帽os ha cambiado mucho el lenguaje.

En pleno 2022 me funciona de esta manera:

instalando dependencia

nom i react-paypal-button-v2

En el componente

import { PayPalButton } from 'react-paypal-button-v2'
...
      <PayPalButton
                        paypalOptions={paypalOptions}
                        buttonStyles={buttonStyles}
                        amount={sumTotalAmount(cart)}
                        onPaymentStart={() => console.log("event paypal")}
                        onPaymentSuccess={data => handlePaymentSuccess(data)}
                        onPaymentError={error => console.log("error ", error)}
                        onPaymentCancel={data => console.log("data cancel ", data)}
                    />

Les comparto algunos problemas que me ocurrieron. Primero no pod铆a instalar react-paypal-button, lo solucion茅 con este comando: npm i react-paypal-button-v2

Segundo, el reto para hacer un outil la funci贸n de handleSumTotal lo resolv铆 as铆:

-Cr茅e la carpeta outils en src y dentro el archivo index.js.
-Copi茅 y peg茅 la funcion de handleSumTotal pero le agregu茅 unos cambios para que funcione:

En s铆 solo hay que agregar 鈥渃art鈥 como parametro y cada vez que quieras usar la funcion en un componente la importas as铆:

import { handleSumTotal } from 鈥樷/utils/index鈥;

Y para usarlo as铆:

<h2>{`Total: $${handleSumTotal(cart)}`}</h2>
amount={handleSumTotal(cart)}

Intent茅 tambien usar dotenv para generar variables de entorno para las paypalOptions (sobre todo para que no quede hardcodeado el clientId) pero no consegu铆 que compile.

Si alguien lo hizo o implement贸 algo similar, ser铆a buenisimo que lo comparta!

P茅sima clase, deber铆an actualizar.
.
Todo lo que se hace, me genera varios errores.

In react-router-dom v6 useHistory() is replaced by useNavigate().

You can use:

import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/home');

Stackoverflow

Hola! para los que le sale el error cuando quieren instalar la dependencia de react-paypal-button-v2
AQUI UNA POSIBLE SOLUCION!!!

npm install react-paypal-button-v2 --save
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: raycris-conf-merch@1.0.0
npm ERR! Found: react@18.0.0
npm ERR! node_modules/react
npm ERR!   react@"^18.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^0.14.6 || 15.x.x || 16.x.x || 17.x.x" from react-paypal-button-v2@2.6.3
npm ERR! node_modules/react-paypal-button-v2
npm ERR!   react-paypal-button-v2@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\Raycris\AppData\Local\npm-cache\eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Raycris\AppData\Local\npm-cache\_logs\2022-04-05T23_37_11_773Z-debug-0.log

SOLAMENTE DEBEMOS DE PONER EL SIGUIENTE COMANDO npm i react-paypal-button-v2 --force, NO ES LO MAS RECOMENDABLE PERO FUNCIONA

En mi caso, como estoy usando NextJS, us茅 el router de Next en vez de useHistory:

https://nextjs.org/docs/api-reference/next/router

Les dejo mi repositorio:

https://github.com/danyel117/platzi-conf-store

Les dejo una documentaci贸n que hice en el curso de webpack por si desean usar variables de entorno para su CLIENT_ID:

Variables de entorno

Es importante considerar las variables de entorno va a ser un espacio seguro donde podemos guardar datos sensibles.

  • Por ejemplo, subir llaves al repositorio no es buena idea cuando tienes un proyecto open source

Para instalar debemos correr el comando.

npm install -D dotenv-webpack

Posteriormente debemos crear un archivo聽.env聽donde estar谩n la clave para acceder a la misma y el valor que contendr谩n (algo importante a tener en cueta es que el archivo .env no se debe enviar al repositorio), aqu铆 es buena idea subir por ejemplo nuestra llave de conexi贸n a una API.

# Ejemplo
API=https://randomuser.me/api/

Es buena idea tener un archivo de ejemplo donde, el mismo si se pueda subir al repositorio como muestra de que campos van a ir.

Una vez creado el archivo聽.env聽debemos agregar la siguiente configuraci贸n en聽webpack.config.js.

...
const Dotenv = require('dotenv-webpack');

module.exports = {
	...
	plugins: [
		new Dotenv()
  ],
}

  • dotenv-webpack 鈬 Leera el archivo聽.env聽por defecto y lo agregar a nuestro proyecto

Para usarlas en JavaScript debes hacer lo siguiente:

const nombre = process.env.NOMBRE_VARIABLE;

Toda la configuraci贸n se podr谩 acceder desde聽process.env.

De esta manera podemos tener informaci贸n delicada de manera segura.

Si al realizar el comando npm i react-paypal-button les sale el error: 鈥淓resolve: unable to resolve dependency three鈥 deben instalar la librer铆a de paypal button pero agreg谩ndole el comando --legacy-peer-deps. En este caso, el comando quedar铆a as铆:

npm install react-paypal-button --save --legacy-peer-deps

Hola en 08-2022 se puede instalar el button con
npm install react-paypal-button-v2 --force

Dejo un video que es un excelente complemento para saber usar el bot贸n de PayPal
https://www.youtube.com/watch?v=nAz8xRQaPZQ

El boton de react paypal me da el sgte error, el clientId esta correcto y el resto de configuracion tal cual la tiene Oscar.

React-paypal-button loading script error:

Make sure that that your clientID is correct and that you are passing valid values to the paypalOptions prop and the buttonStyles prop.

For a list of valid properties for paypalOptions see https://developer.paypal.com/docs/checkout/reference/customize-sdk/#query-parameters
For a list of valid properties for buttonStyles see https://developer.paypal.com/docs/checkout/integration-features/customize-button/#color

Parece que el paquete react-paypal-button requiere tener una versi贸n menor de la 17 de react si no da un error al instalarla, as铆 que instalen una 16.8.x

A mi me sirvi贸 con el siguiente comando en la terminal:

npm install react-paypal-button --save

ya se puede usar useHistory quedaria algo asi

import { useHistory } from 'react-router-dom';

const history = useHistory();


  const handlePaymentSuccess = (data) => {
    console.log(data);
    if (data.status === 'COMPLETED') {
      const newOrder = {
        buyer,
        product: cart,
        payment: data,
      };
      addNewOrder(newOrder);
      history.push('/checkout/success');
    }
  };```

le agregue como componente con el nombre PayPal.jsx

import { useEffect } from "react";
import {PayPalScriptProvider, PayPalButtons,usePayPalScriptReducer} from "@paypal/react-paypal-js";
const amount = "2";
const currency = "USD";
const style = {"layout":"vertical"};


const ButtonWrapper = ({ currency, showSpinner }) => {

    const [{ options, isPending }, dispatch] = usePayPalScriptReducer();

    useEffect(() => {
        dispatch({
            value: {
                ...options,
                currency: currency,
            },
        });
    }, [currency, showSpinner]);


    return (<>
            { (showSpinner && isPending) && <div className="spinner" /> }
            <PayPalButtons
                style={style}
                disabled={false}
                forceReRender={[amount, currency, style]}
                fundingSource={undefined}
                createOrder={(data, actions) => {
                    return actions.order
                        .create({
                            purchase_units: [
                                {
                                    amount: {
                                        currency_code: currency,
                                        value: amount,
                                    },
                                },
                            ],
                        })
                        .then((orderId) => {
                            // Your code here after create the order
                            return orderId;
                        });
                }}
                onApprove={function (data, actions) {
                    return actions.order.capture().then(function () {
                        // Your code here after capture the order
                    });
                }}
            />
        </>
    );
}

export default function App() {
	return (
		<div style={{ maxWidth: "750px", minHeight: "200px" }}>
            <PayPalScriptProvider
                options={{
                    "client-id": "test",
                    components: "buttons",
                    currency: "USD"
                }}
            >
				<ButtonWrapper
                    currency={currency}
                    showSpinner={false}
                />
			</PayPalScriptProvider>
		</div>
	);
}

y en payment le deje de esta manera la cual me permite tener el total de productos y el valor a pagar y genere el pago con tarjeta de cr茅dito

import React, { useContext } from 'react';
import AppContext from '../context/AppContext';
import '../styles/components/Payment.css';
import PayPal from './PayPal'

const Payment = () => {
  const { state: { cart }, removeToCart } = useContext(AppContext);

  const handleRemote = product => {
    removeToCart(product)
  }

  const handleSumtotal = () => {
    const reducer = (accumulator, currentValue) => accumulator + (currentValue.price * currentValue.qty);
    const sum = cart.reduce(reducer, 0);
    return sum;
  }

  return (
    <div className="Payment">
      <div className="Payment-content">
        <h3>Resument del pedido:</h3>
        
  {cart.length > 0
          ? <>
            {cart.map(product => (
              <div key={product.id} className="Checkout-item">
                <div className="Checkout-element">
                  <h4>{product.title}</h4>
                  <span>Cant. {product.qty}</span>
                  <span>$ {product.price}</span>
                  <span>Total: $ {product.price * product.qty}</span>
                </div>

              </div>
            ))}
             <h3>Precio Total: {handleSumtotal()}</h3>
          </>
          : <p>No hay Articulos en el carrito</p>}


        <div className="Payment-button">
          
         <PayPal/>
        </div>
      </div>
      <div />
    </div>
  );
}

export default Payment;

Llevando totalizador a un utilitario

const sumTotal = (arr, field) => {
    const reducer = (accumulator, currentValue) =>
      accumulator + currentValue[field];
    const sum = arr.reduce(reducer, 0);
    return sum;
  };

export {
    sumTotal
}

Si a alguien le sale el siguiente error instalando la dependencia del boton de Paypal

Lo puede solucionar intentando instalar la dependencia asi:

npm i react-paypal-button-v2 --legacy-peer-deps

驴Por qu茅 oculta el clientId en el video y en los archivos adjuntos lo muestra? 驴Lo cambi贸 en los archivos u olvid贸 ocultarlo?

b