├── .gitignore ├── README.md ├── bun.lockb ├── components.json ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public └── vite.svg ├── src ├── App.css ├── App.tsx ├── AppHookContainer.tsx ├── AppRouter.tsx ├── ErrorBoundary.tsx ├── assets │ └── react.svg ├── components │ ├── Button │ │ ├── Button.css │ │ └── Button.tsx │ ├── ErrorBoundaryExamples │ │ ├── EffectExample.tsx │ │ ├── PromiseError.tsx │ │ ├── UndefinedExample.tsx │ │ └── index.ts │ ├── Form │ │ └── Form.tsx │ ├── Modal │ │ ├── Modal.css │ │ ├── Modal.tsx │ │ └── context │ │ │ ├── ModalContext.tsx │ │ │ ├── UseModalContext.ts │ │ │ └── index.ts │ ├── RoutesWithNotFound │ │ └── RoutesWithNotFound.tsx │ ├── UseCallback │ │ └── PhoneBook.tsx │ ├── UseMemo │ │ └── ShoppingCart.tsx │ ├── UseRef │ │ ├── BookReader.tsx │ │ ├── FocusInput.tsx │ │ └── index.ts │ └── index.ts ├── context │ ├── global.context.ts │ └── global.provider.tsx ├── guard │ └── PrivateGuard.tsx ├── hooks │ ├── index.ts │ ├── useApi.ts │ └── useFetch.ts ├── index.css ├── main.tsx ├── models │ ├── character.model.ts │ ├── index.ts │ ├── routes.model.ts │ ├── useApi.model.ts │ └── user.model.ts ├── private │ ├── Dashboard │ │ └── Dashboard.tsx │ └── PrivateRouter.tsx ├── public │ └── Login │ │ └── Login.tsx ├── services │ ├── api.service.ts │ ├── axios.service.ts │ ├── index.ts │ └── share-value-children.service.ts ├── utilities │ ├── index.ts │ └── loadAbort.utility.ts └── vite-env.d.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ¡Bienvenidos a mi Curso de React en Vivo! 2 | 3 | 4 | Este repositorio es donde la magia sucede. Aquí documentaré cada paso de mi curso de React, transmitido en vivo para que aprendamos juntos. Usaremos Bun, Vite.js, TypeScript y React para construir aplicaciones increíbles, ¡y tú serás parte del proceso! 5 | 6 | ### Estructura del Repositorio 7 | 8 | * **Commits:** Cada commit representa una lección, un concepto clave o un momento épico de nuestras sesiones en vivo. 9 | 10 | * **Branches:** Las branches principales se organizan por secciones o módulos del curso, con nombres como `clase-01`, `clase-02`, etc. 11 | * **Código:** El código fuente de nuestras creaciones con React, construido con Bun, Vite.js, TypeScript y React, evolucionará en la rama principal a medida que avancemos juntos. 12 | 13 | 14 | ### Redes 15 | 16 | [https://doras.to/gentleman-programming](https://doras.to/gentleman-programming) 17 | 18 | ### Cómo Sacarle el Máximo Provecho 19 | 20 | 1. **Clona el repositorio:** `git clone https://docs.github.com/es/repositories` 21 | 2. **Instala las dependencias:** `bun install` 22 | 3. **¡Únete a mis streams!** Sígueme en YouTube, Kick y Twitch para no perderte ninguna sesión en vivo (link arriba). 23 | 4. **Explora las branches:** `git checkout clase-XX` (reemplaza XX con el número de clase que te interese) 24 | 5. **Revisa los commits:** `git log` para ver la historia de nuestro progreso juntos. 25 | 6. **¡Pregunta, comenta, participa!** Este curso es interactivo, ¡así que no te quedes con dudas! 26 | 27 | ### Contribuciones 28 | 29 | 30 | Aunque este repositorio es principalmente para documentar el curso, si tienes alguna sugerencia, corrección o mejora ¡no dudes en abrir un issue o pull request! ¡Tu aporte es valioso! 31 | 32 | **¡Nos vemos en los streams! ¡Vamos a dominar React juntos!** 🚀 33 | 34 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gentleman-Programming/React-Desde-0-a-Avanzado/d8640cbde165b46f450bd3f227042acc8d150dcb/bun.lockb -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | import tseslint from 'typescript-eslint' 6 | 7 | export default tseslint.config( 8 | { ignores: ['dist'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | }, 28 | ) 29 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |Navbar
13 | {children} 14 |Footer
15 | > 16 | ) 17 | } 18 | 19 | export default App 20 | -------------------------------------------------------------------------------- /src/AppHookContainer.tsx: -------------------------------------------------------------------------------- 1 | 2 | import App from './App' 3 | import './App.css' 4 | import { AppRouter } from './AppRouter' 5 | import { ModalProvider } from './components/Modal/context' 6 | import { GlobalProvider } from './context/global.provider' 7 | import ErrorBoundary from './ErrorBoundary' 8 | 9 | function AppHookContainer() { 10 | return ( 11 |Teléfono: {contact.phone}
29 | 30 |{log}
68 |Costo Total: ${totalCost.toFixed(2)}
64 | 65 |66 | Descuento: $ 67 | setDiscount(parseFloat(e.target.value) || 0)} /> 68 |
69 | 70 |Costo Final: ${finalCost.toFixed(2)}
71 | 72 | 73 |Página actual: {currentPageRef.current}
45 |Página actual [ STATE ]: {currentPage}
46 | 47 | 48 | 49 | = {
5 | autoFetch?: boolean;
6 | params: P
7 | }
8 |
9 |
10 | type Data ): UseApiResultEsto es el Dashboard !
3 | }
4 |
--------------------------------------------------------------------------------
/src/private/PrivateRouter.tsx:
--------------------------------------------------------------------------------
1 | import { Navigate, Route, Routes } from "react-router-dom"
2 | import { Dashboard } from "./Dashboard/Dashboard"
3 | import { RoutesWithNotFound } from "@/components/RoutesWithNotFound/RoutesWithNotFound"
4 | import { AppRoutes } from "@/models"
5 |
6 | export const PrivateRouter = () => {
7 | return (
8 | Esto es el Login !!!
3 | }
4 |
--------------------------------------------------------------------------------
/src/services/api.service.ts:
--------------------------------------------------------------------------------
1 | const BASE_URL = "https://rickandmortyapi.com/api"
2 | import { Character, UseApiCall } from "@/models"
3 | import { loadAbort } from "../utilities"
4 | import axios from "axios"
5 |
6 | export const getCharacter = (id: number): UseApiCall