From c532d20d1205440325065a97f5ef608107f9494c Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 4 Aug 2025 19:52:34 +0200 Subject: [PATCH 01/31] boiler plate --- .../02-base/react-boiler-plate/.gitignore | 24 +++++++ .../02-base/react-boiler-plate/README.md | 69 +++++++++++++++++++ .../react-boiler-plate/eslint.config.js | 23 +++++++ .../02-base/react-boiler-plate/index.html | 13 ++++ .../02-base/react-boiler-plate/package.json | 30 ++++++++ .../02-base/react-boiler-plate/src/app.tsx | 26 +++++++ .../02-base/react-boiler-plate/src/main.tsx | 9 +++ .../react-boiler-plate/src/vite-env.d.ts | 1 + .../02-base/react-boiler-plate/tsconfig.json | 20 ++++++ .../02-base/react-boiler-plate/vite.config.ts | 8 +++ 10 files changed, 223 insertions(+) create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/.gitignore create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/README.md create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/index.html create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/package.json create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json create mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore b/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/README.md b/04-frameworks/01-react/02-base/react-boiler-plate/README.md new file mode 100644 index 000000000..7959ce426 --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/README.md @@ -0,0 +1,69 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + ...tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + ...tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + ...tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js b/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js new file mode 100644 index 000000000..d94e7deb7 --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/index.html b/04-frameworks/01-react/02-base/react-boiler-plate/index.html new file mode 100644 index 000000000..3dcb3bc5b --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/package.json b/04-frameworks/01-react/02-base/react-boiler-plate/package.json new file mode 100644 index 000000000..d3b4ff0b0 --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/package.json @@ -0,0 +1,30 @@ +{ + "name": "react-boiler-plate", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.30.1", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "eslint": "^9.30.1", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.35.1", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.2" + } +} diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx b/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx new file mode 100644 index 000000000..c50d41a18 --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx @@ -0,0 +1,26 @@ +import { useState } from "react"; + +interface AppProps { + initialCount: number; +} + +export const App: React.FC = ({ initialCount }) => { + const [count, setCount] = useState(initialCount); + + return ( + <> +

Vite + React

+
+ +

+ Edit src/App.tsx and save to test HMR +

+
+

+ Click on the Vite and React logos to learn more +

+ + ); +}; diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx b/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx new file mode 100644 index 000000000..2cfa679db --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; + +createRoot(document.getElementById("root")!).render( + + + +); diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts b/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json b/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json new file mode 100644 index 000000000..4cd6cb84c --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true, + "allowImportingTsExtensions": false + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts b/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts new file mode 100644 index 000000000..7273768f9 --- /dev/null +++ b/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import checker from "vite-plugin-checker"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), checker({ typescript: true })], +}); From 339eaba7b0ca8b2dd885a0028ea4fcb7e0b5defa Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 25 Aug 2025 07:50:01 +0200 Subject: [PATCH 02/31] refactor: update react boiler plate to vite --- .../02-base/01-create-react-app/readme.md | 33 ----- .../02-base/01-create-react-app/readme_es.md | 44 ------- .../01-react/02-base/01-vite-boiler/README.md | 23 ++++ .../src => 01-vite-boiler}/index.html | 8 +- .../02-base/01-vite-boiler/package.json | 17 +++ .../02-base/01-vite-boiler/src/index.ts | 1 + .../02-base/01-vite-boiler/tsconfig.json | 18 +++ .../02-base/01-vite-boiler/vite.config.ts | 6 + .../01-react/02-base/02-vite-react/index.html | 13 ++ .../02-base/02-vite-react/package.json | 22 ++++ .../01-react/02-base/02-vite-react/readme.md | 92 ++++++++++++++ .../readme_es.md | 0 .../src/app.tsx | 0 .../src/index.tsx | 4 +- .../02-base/02-vite-react/tsconfig.json | 19 +++ .../02-base/02-vite-react/vite.config.ts | 7 ++ .../02-base/02-webpack-boiler/.babelrc | 3 - .../02-base/02-webpack-boiler/package.json | 32 ----- .../02-base/02-webpack-boiler/readme.md | 20 --- .../02-base/02-webpack-boiler/readme_es.md | 20 --- .../02-base/02-webpack-boiler/src/index.html | 12 -- .../02-base/02-webpack-boiler/src/index.tsx | 1 - .../02-base/02-webpack-boiler/src/styles.css | 3 - .../02-base/02-webpack-boiler/tsconfig.json | 18 --- .../02-webpack-boiler/webpack.config.js | 54 --------- .../02-base/03-webpack-react/.babelrc | 7 -- .../02-base/03-webpack-react/package.json | 39 ------ .../02-base/03-webpack-react/readme.md | 114 ------------------ .../02-base/03-webpack-react/src/styles.css | 3 - .../02-base/03-webpack-react/tsconfig.json | 18 --- .../03-webpack-react/webpack.config.js | 54 --------- 31 files changed, 224 insertions(+), 481 deletions(-) delete mode 100644 04-frameworks/01-react/02-base/01-create-react-app/readme.md delete mode 100644 04-frameworks/01-react/02-base/01-create-react-app/readme_es.md create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/README.md rename 04-frameworks/01-react/02-base/{03-webpack-react/src => 01-vite-boiler}/index.html (55%) create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/package.json create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/src/index.ts create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/tsconfig.json create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/vite.config.ts create mode 100644 04-frameworks/01-react/02-base/02-vite-react/index.html create mode 100644 04-frameworks/01-react/02-base/02-vite-react/package.json create mode 100644 04-frameworks/01-react/02-base/02-vite-react/readme.md rename 04-frameworks/01-react/02-base/{03-webpack-react => 02-vite-react}/readme_es.md (100%) rename 04-frameworks/01-react/02-base/{03-webpack-react => 02-vite-react}/src/app.tsx (100%) rename 04-frameworks/01-react/02-base/{03-webpack-react => 02-vite-react}/src/index.tsx (58%) create mode 100644 04-frameworks/01-react/02-base/02-vite-react/tsconfig.json create mode 100644 04-frameworks/01-react/02-base/02-vite-react/vite.config.ts delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/.babelrc delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/package.json delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/readme.md delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/readme_es.md delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/src/index.html delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/src/index.tsx delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/src/styles.css delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/tsconfig.json delete mode 100644 04-frameworks/01-react/02-base/02-webpack-boiler/webpack.config.js delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/.babelrc delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/package.json delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/readme.md delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/src/styles.css delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/tsconfig.json delete mode 100644 04-frameworks/01-react/02-base/03-webpack-react/webpack.config.js diff --git a/04-frameworks/01-react/02-base/01-create-react-app/readme.md b/04-frameworks/01-react/02-base/01-create-react-app/readme.md deleted file mode 100644 index 28562cc61..000000000 --- a/04-frameworks/01-react/02-base/01-create-react-app/readme.md +++ /dev/null @@ -1,33 +0,0 @@ -# Create React app - -To create such an application - -https://create-react-app.dev/ - -````bash -npx create-react-app my-app -``` - -How to upgrade - -````bash -npm install react-scripts@latest -``` - -Discuss what _npx_ is and why not _npm install create-react-app -g_ - -Comment on structure, and comment on how to create _typescript_ project - -npx create-react-app my-app --template typescript - -And add _TypeScript_ support afterwards - -https://create-react-app.dev/docs/adding-typescript - -Comment eject and you won't see what's going on. - -https://create-react-app.dev/docs/available-scripts/#npm-run-eject - -And more fumada customizing and making your template - -https://auth0.com/blog/how-to-configure-create-react-app/ diff --git a/04-frameworks/01-react/02-base/01-create-react-app/readme_es.md b/04-frameworks/01-react/02-base/01-create-react-app/readme_es.md deleted file mode 100644 index 61abf417b..000000000 --- a/04-frameworks/01-react/02-base/01-create-react-app/readme_es.md +++ /dev/null @@ -1,44 +0,0 @@ -# Create React app - -Para crear una aplicación de este tipo - -https://create-react-app.dev/ - -```bash -npx create-react-app my-app -``` - -Si te da algún problema de versión antigua, prueba a borrar la caché de _npx_ - -```bash -sudo npx clear-npx-cache -``` - -Si un día necesitas hacer un upgrade de un proyecto existente, lo puedes hacer ejecutando el siguiente comando: - -```bash -npm install react-scripts@latest -``` - -Utilizamos _npx_ para traernos siempre la última versión de _create-react-app_. Si lo hicieramos con _npm install create-react-app -g_, -nos instalaría la versión actual en nuestra máquina de forma global, y si creamos una aplicación en un tiempo no utilizaría la última versión. - -Para crear un proyecto con soporte para _typescript_: - -```bash -npx create-react-app my-app --template typescript -``` - -O añadir soporte a _TypeScript_ después: - -https://create-react-app.dev/docs/adding-typescript - -Podemos hacer `eject` de nuestro proyecto y tener acceso directo a la configuración (por ejemplo, de _webpack_): - -https://create-react-app.dev/docs/available-scripts/#npm-run-eject - -Podemos comprobar abriendo la configuración de _webpack_ que es inmanejable. - -Y más fumada customizando y haciendo tu plantilla - -https://auth0.com/blog/how-to-configure-create-react-app/ diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/README.md b/04-frameworks/01-react/02-base/01-vite-boiler/README.md new file mode 100644 index 000000000..04c711949 --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/README.md @@ -0,0 +1,23 @@ +## 02 Web Boiler plate + +## Summary + +In this example there is a vite boiler plate set up with Typescript support, just in the step before +to adding React support. + +It is based on the Vite examples. + +This example is the only one that doesn't have a step-by-step (if you need guidance, you can go to the +vite examples you'll find in this repository). + +Highlights: + +- Added TypeScript as a local dev dependency. +- Switch project to use ES Modules in package.json. +- Create a `tsconfig.json` with a minimal configuration. +- Vite uses esbuild for transpilation (fast, no type checking). +- Enable isolatedModules and `useDefineForClassFields` for `esbuild`compatibility. +- Type checking is handled separately (via tsc or IDE). + +In the following example we will take this as a starting point and we will go step by step adding +support for React. diff --git a/04-frameworks/01-react/02-base/03-webpack-react/src/index.html b/04-frameworks/01-react/02-base/01-vite-boiler/index.html similarity index 55% rename from 04-frameworks/01-react/02-base/03-webpack-react/src/index.html rename to 04-frameworks/01-react/02-base/01-vite-boiler/index.html index a3d74b719..dd5f1546a 100644 --- a/04-frameworks/01-react/02-base/03-webpack-react/src/index.html +++ b/04-frameworks/01-react/02-base/01-vite-boiler/index.html @@ -1,12 +1,12 @@ - - - - My App Example + + +
+ diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/package.json b/04-frameworks/01-react/02-base/01-vite-boiler/package.json new file mode 100644 index 000000000..964563240 --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/package.json @@ -0,0 +1,17 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + } +} diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/src/index.ts b/04-frameworks/01-react/02-base/01-vite-boiler/src/index.ts new file mode 100644 index 000000000..f69b4850f --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/src/index.ts @@ -0,0 +1 @@ +console.log("Vite-boiler-plate"); diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/tsconfig.json b/04-frameworks/01-react/02-base/01-vite-boiler/tsconfig.json new file mode 100644 index 000000000..6414575cc --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/vite.config.ts b/04-frameworks/01-react/02-base/01-vite-boiler/vite.config.ts new file mode 100644 index 000000000..5bfe487c0 --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; + +export default defineConfig({ + plugins: [checker({ typescript: true })], +}); diff --git a/04-frameworks/01-react/02-base/02-vite-react/index.html b/04-frameworks/01-react/02-base/02-vite-react/index.html new file mode 100644 index 000000000..855767d12 --- /dev/null +++ b/04-frameworks/01-react/02-base/02-vite-react/index.html @@ -0,0 +1,13 @@ + + + + + + Vite App + + + +
+ + + diff --git a/04-frameworks/01-react/02-base/02-vite-react/package.json b/04-frameworks/01-react/02-base/02-vite-react/package.json new file mode 100644 index 000000000..b76d9beec --- /dev/null +++ b/04-frameworks/01-react/02-base/02-vite-react/package.json @@ -0,0 +1,22 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + } +} diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme.md b/04-frameworks/01-react/02-base/02-vite-react/readme.md new file mode 100644 index 000000000..24fb9880a --- /dev/null +++ b/04-frameworks/01-react/02-base/02-vite-react/readme.md @@ -0,0 +1,92 @@ +# 02 Vite React + +## Summary + +This example takes the _01-vite-boiler_ example as a starting point. + +We will go step by step adding the necessary configuration so that we integrate +**React** into our build process. + +# Step by Step guide + +- First we copy the previous example, and do a _npm install_ + +```bash +npm install +``` + +- Next, install `react` and `react-dom` dependencies: + +```bash +npm install react react-dom --save +``` + +- Now open `tsconfig.json` file and set following compiler option to support `jsx` notation in our TypeScript files: + + _tsconfig.json_ + + ```diff + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + ``` + + ⚡ `jsx` is a JavaScript syntax extension that will allow us to write HTML-in-JS and is typically used by React components. + +- In order to make `vite` fully support `jsx` syntax (among other things) we will add a plugin, otherwise, `esbuild` won't be able to transpile our `react` source files written in `jsx` syntax: + + ```bash + npm install @vitejs/plugin-react --save-dev + ``` + +- Finally, let's modify `vite.config.ts` to add the newly installed plugin: + + _vite.config.ts_ + + ```diff + import { defineConfig } from "vite"; + import checker from "vite-plugin-checker"; + + import react from "@vitejs/plugin-react"; + + export default defineConfig({ + - plugins: [checker({ typescript: true })], + + plugins: [checker({ typescript: true }), react()], + }); + + ``` + +- Let's create our first React component. + +_./src/app.tsx_ + +```tsx +import React from "react"; + +export const App = () => { + return

Hello React !!

; +}; +``` + +- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _createRoot_. + +Lets update our _./src/index.ts_ to _./src/index.tsx_ + +```tsx +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; + +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); + +root.render(); +``` + +- Let's check that things are working as expected: + +```bash +npm start +``` diff --git a/04-frameworks/01-react/02-base/03-webpack-react/readme_es.md b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md similarity index 100% rename from 04-frameworks/01-react/02-base/03-webpack-react/readme_es.md rename to 04-frameworks/01-react/02-base/02-vite-react/readme_es.md diff --git a/04-frameworks/01-react/02-base/03-webpack-react/src/app.tsx b/04-frameworks/01-react/02-base/02-vite-react/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/02-base/03-webpack-react/src/app.tsx rename to 04-frameworks/01-react/02-base/02-vite-react/src/app.tsx diff --git a/04-frameworks/01-react/02-base/03-webpack-react/src/index.tsx b/04-frameworks/01-react/02-base/02-vite-react/src/index.tsx similarity index 58% rename from 04-frameworks/01-react/02-base/03-webpack-react/src/index.tsx rename to 04-frameworks/01-react/02-base/02-vite-react/src/index.tsx index 7e439b87e..f323553ef 100644 --- a/04-frameworks/01-react/02-base/03-webpack-react/src/index.tsx +++ b/04-frameworks/01-react/02-base/02-vite-react/src/index.tsx @@ -2,7 +2,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; -const container = document.getElementById("root"); -const root = createRoot(container); +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); root.render(); diff --git a/04-frameworks/01-react/02-base/02-vite-react/tsconfig.json b/04-frameworks/01-react/02-base/02-vite-react/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/02-base/02-vite-react/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/02-base/02-vite-react/vite.config.ts b/04-frameworks/01-react/02-base/02-vite-react/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/02-base/02-vite-react/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/.babelrc b/04-frameworks/01-react/02-base/02-webpack-boiler/.babelrc deleted file mode 100644 index 3313ff9ef..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env", "@babel/preset-typescript"] -} diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/package.json b/04-frameworks/01-react/02-base/02-webpack-boiler/package.json deleted file mode 100644 index 9b1b0de5c..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-typescript": "^7.16.7", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - } -} diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/readme.md b/04-frameworks/01-react/02-base/02-webpack-boiler/readme.md deleted file mode 100644 index 5fe86d280..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/readme.md +++ /dev/null @@ -1,20 +0,0 @@ -## 02 Web Boiler plate - -## Summary - -In this example there is a webpack boiler plate set up with Typescript support, just in the step before -to adding React support. - -It is based on the Webpack examples. - -This example is the only one that doesn't have a step-by-step (if you need guidance, you can go to the -webpack examples you'll find in this repository). - -Highlights: - -- The webpackconfig has the src folder configured, and the loaders to handle typescript. -- We have babel and typescript configuration files. -- We do the transpilation using babel. - -In the following example we will take this as a starting point and we will go step by step adding -support for React. diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/readme_es.md b/04-frameworks/01-react/02-base/02-webpack-boiler/readme_es.md deleted file mode 100644 index abab80d66..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/readme_es.md +++ /dev/null @@ -1,20 +0,0 @@ -# 02 Web Boiler plate - -## Resumen - -En este ejemplo hay montado un boiler plate en webpack con soporte a Typescript, justo en el paso previo -a añadirle soporte a React. - -Está basado en los ejemplos de Webpack. - -Este ejemplo es el único que no tiene un paso a paso (si necesitas guía puedes ir a los ejemplos -de webpack que encontrarás en este repositorio). - -A destacar: - -- El webpackconfig tiene configurada la carpeta src, y los loaders para manejar typescript. -- Tenemos ficheros de configuracion de babel y typescript. -- Hacemos la transpilación utlizando babel. - -En el siguiente ejemplo tomaremos este como punto de partida y si iremos paso a paso añadiendo -soporte a React. diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.html b/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.html deleted file mode 100644 index 26e6c384d..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -

Hello World !

- - diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.tsx b/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.tsx deleted file mode 100644 index 8e1bb81b1..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/src/index.tsx +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello from JS"); diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/src/styles.css b/04-frameworks/01-react/02-base/02-webpack-boiler/src/styles.css deleted file mode 100644 index 74dc08fbb..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.my-text { - color: blue; -} diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/tsconfig.json b/04-frameworks/01-react/02-base/02-webpack-boiler/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/02-base/02-webpack-boiler/webpack.config.js b/04-frameworks/01-react/02-base/02-webpack-boiler/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/02-base/02-webpack-boiler/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/02-base/03-webpack-react/.babelrc b/04-frameworks/01-react/02-base/03-webpack-react/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/02-base/03-webpack-react/package.json b/04-frameworks/01-react/02-base/03-webpack-react/package.json deleted file mode 100644 index 50e9c4ccc..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" - } -} diff --git a/04-frameworks/01-react/02-base/03-webpack-react/readme.md b/04-frameworks/01-react/02-base/03-webpack-react/readme.md deleted file mode 100644 index 9efb29473..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/readme.md +++ /dev/null @@ -1,114 +0,0 @@ -# 03 Webpack React - -## Summary - -This example takes the _02-webpack-boiler_ example as a starting point. - -We will go step by step adding the necessary configuration so that we integrate -**React** into our build process. - -# Step by Step guide - -- First we copy the previous example, and do a _npm install_ - -```bash -npm install -``` - -- Let's install _react_ and _react-dom_ - -```bash -npm install react react-dom --save -``` - -- Let's install _react_ and _react-dom_ typings - -```bash -npm install @types/react @types/react-dom --save-dev -``` - -This way we have the React library and the bindings to integrate with a web browser. - -- In the index.html we are going to put the _div_ that will serve as entry point to instantiate our React application. our React application. - -_./src/index.html_ - -```diff - --

Hello World !

-+
- -``` - -- Let's create our first React component. - -_./src/app.tsx_ - -```tsx -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; -``` - -- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _createRoot_. - -_./src/index.tsx_ - -```tsx -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -const rootElement = document.getElementById("root"); -const root = createRoot(rootElement); - -root.render(); -``` - -- We are on the right track, but if we try to run this it will fail, since _babel_ does not know how to transform the _jsx_ (remember that this was a sugar, which was actually an XML) into javaScript, in order for babel to be able to understand this we have to install the _preset_ _@babel/preset-react_ - -First we install it and the configure it. - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> By the way the _rc_ suffix is pretty usual in linux it's stands for "runcom" -> (CTSS system 1962-63) Script file containing startup instructions for an application program. -> In other words, "rc" is just something that stuck from back in the sixties, and has been used quite often for configuration files in different sorts of programs since, including Node, Babel and many, many others. -> More info [on stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Another curiosity... what is a _preset_ ... let's start with what is a babel plugin: babel transformations are -> enabled by applying plugins, there are plenty of plugins and if you have to go adding one by one it can become a nightmare, -> in order to make this easier, babel has grouped common sets of plugins in _presets_, for instance @babel-preset-react -> includes the following plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Is time to double check the _webpack.config.js_ - -- We can make sure that we have _ts_ and _tsx_ as valid extensions. -- Also that in the loader we accept both _ts_ and _tsx_. -- And in the app we have as entry point _index.tsx_. - -* Let's check that things are working as expected: - -```bash -npm start -``` diff --git a/04-frameworks/01-react/02-base/03-webpack-react/src/styles.css b/04-frameworks/01-react/02-base/03-webpack-react/src/styles.css deleted file mode 100644 index 74dc08fbb..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.my-text { - color: blue; -} diff --git a/04-frameworks/01-react/02-base/03-webpack-react/tsconfig.json b/04-frameworks/01-react/02-base/03-webpack-react/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/02-base/03-webpack-react/webpack.config.js b/04-frameworks/01-react/02-base/03-webpack-react/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/02-base/03-webpack-react/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From c88233aab66f233ee9ba2324af273f63d02559a9 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 25 Aug 2025 22:29:03 +0200 Subject: [PATCH 03/31] translate vite boiler to spanish --- .../01-react/02-base/01-vite-boiler/README.md | 6 +- .../02-base/01-vite-boiler/readme_es.md | 23 ++++ .../01-react/02-base/02-vite-react/readme.md | 4 +- .../02-base/02-vite-react/readme_es.md | 116 +++++++----------- 4 files changed, 72 insertions(+), 77 deletions(-) create mode 100644 04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/README.md b/04-frameworks/01-react/02-base/01-vite-boiler/README.md index 04c711949..bf1aaebfc 100644 --- a/04-frameworks/01-react/02-base/01-vite-boiler/README.md +++ b/04-frameworks/01-react/02-base/01-vite-boiler/README.md @@ -13,10 +13,10 @@ vite examples you'll find in this repository). Highlights: - Added TypeScript as a local dev dependency. -- Switch project to use ES Modules in package.json. -- Create a `tsconfig.json` with a minimal configuration. +- Switched project to use ES Modules in package.json. +- Created a `tsconfig.json` with a minimal configuration. - Vite uses esbuild for transpilation (fast, no type checking). -- Enable isolatedModules and `useDefineForClassFields` for `esbuild`compatibility. +- Enabled `isolatedModules` and `useDefineForClassFields` for `esbuild`compatibility. - Type checking is handled separately (via tsc or IDE). In the following example we will take this as a starting point and we will go step by step adding diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md b/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md new file mode 100644 index 000000000..f8eeb987b --- /dev/null +++ b/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md @@ -0,0 +1,23 @@ +## 02 Web Boiler plate + +## Resumen + +En este ejemplo desarrollamos un boilerplate de Vite configurado con soporte para TypeScript, justo en el paso previo +a añadir soporte para React. + +Está basado en los ejemplos de Vite. + +Este ejemplo es el único que no tiene una guía paso a paso (si necesitas orientación, puedes consultar los +ejemplos de Vite que encontrarás en este repositorio). + +Puntos destacados: + +- Se agregó TypeScript como dependencia de desarrollo local. +- Se cambió el proyecto para usar ES Modules `package.json`. +- Se creó un `tsconfig.json` con una configuración mínima. +- Vite utiliza esbuild para la transpilación (rápido, sin comprobación de tipos). +- Se habilitó `isolatedModules` y `useDefineForClassFields` para que sea compatible con `esbuild`. +- La comprobación de tipos se maneja por separado (a través de tsc o del IDE). + +En el siguiente ejemplo tomaremos este como punto de partida y, paso a paso, añadiremos +soporte para React. diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme.md b/04-frameworks/01-react/02-base/02-vite-react/readme.md index 24fb9880a..ed3f4cff2 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme.md @@ -70,9 +70,9 @@ export const App = () => { }; ``` -- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _createRoot_. +Lets update our _./src/index.ts_ to _./src/index.tsx_. We also adjust in the _./index.html_ file. -Lets update our _./src/index.ts_ to _./src/index.tsx_ +- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _createRoot_. ```tsx import React from "react"; diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md index bb34f2812..d575f2b85 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md @@ -1,47 +1,63 @@ -# 03 Webpack React +# 02 Vite React -## Resumen +## Summary -Este ejemplo toma como punto de partida el ejemplo _02-webpack-boiler_. +Este ejemplo parte desde el ejemplo _01-vite-boiler_. -Vamos a ir paso a paso añdiendo la configuración necesaria para que integrar -**React** en nuestro proceso de build. +Vamos a ir paso a paso, añadiendo la configuración necesaria para integrar **React**. -## Paso a Paso +# Guía paso a paso -- Primero copiamos el ejemplo anterior, y hacemos un _npm install_ +- Antes que nada nos instalamos todos los paquetes necesarios del boiler plate ejecutando _npm install_ ```bash npm install ``` -- Vamos a instalar _react_ y _react-dom_ +- A continuación instalamos `react` y `react-dom` como dependencias: ```bash npm install react react-dom --save ``` -- Vamos a instalarnos los typing de _react_ y _react-dom_ +- Para hacer que TS entienda la notación `jsx` añadimos lo siguiente en el fichero `tsconfig.json`: -```bash -npm install @types/react @types/react-dom --save-dev -``` + _tsconfig.json_ -Así tenemos la librería de React y los bindings para que se integre con un navegador web. + ```diff + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + ``` -- En el index.html vamos a meter el _div_ que nos servirá como punto de entrada para instanciar - nuestra aplicación React. + ⚡ `jsx` es azucar sintáctico que permite escribir HTML-in-JS. Esta sintaxis es la que vamos a usar con los componentes de React. -_./src/index.html_ +- Para hacer que `vite` soporte la sintaxis `jsx` (y otras cosas) tenemos que añadir un plugin, sino, `esbuild` no será capaz de transpilar nuestros ficheros de `react`, escritos en formato en `jsx`: -```diff - --

Hello World !

-+
- -``` + ```bash + npm install @vitejs/plugin-react --save-dev + ``` + +- Finalmente, modificamos `vite.config.ts` añadiendo nuestro plugin: + + _vite.config.ts_ + + ```diff + import { defineConfig } from "vite"; + import checker from "vite-plugin-checker"; + + import react from "@vitejs/plugin-react"; -- Vamos a crear nuestro primero componente React. + export default defineConfig({ + - plugins: [checker({ typescript: true })], + + plugins: [checker({ typescript: true }), react()], + }); + + ``` + +- Creemos ahora nuestro primer componente _./src/app.tsx_ @@ -53,66 +69,22 @@ export const App = () => { }; ``` -- Es hora de instanciar ese compente principal, para poder integrarlo con el navegador - tenemos que hacer uso a _ReactDOM.render_ +Actualizamos*./src/index.ts* a _./src/index.tsx_. Ajustamos la extensión también en el fichero _./index.html_. -_./src/index.tsx_ +- Vamos a usar el componente que acabamos de crear. Para poder integrar ese componente (y el resto de la aplicación) en nuestro html, hacemos uso de _createRoot_. ```tsx import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; -const container = document.getElementById("root"); -const root = createRoot(container); +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); root.render(); ``` -- Vamos por buen camino, pero si intentamos ejecutar esto no va fallar, ya que _babel_ no sabe - como transformar el _jsx_ (recordemos que esto era un azúcar, que en realidad era un XML) a - javaScript, para que babel sea capaz de entender esto tenemos que instalar el _preset_ - _@babel/preset-react_ - -Primero lo instalamos - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> Por cierto, el sufijo _rc_ es bastante habitual en linux, significa "runcom". -> (Sistema CTSS 1962-63) Archivo de script que contiene instrucciones de inicio para un programa de aplicación. -> En otras palabras, "rc" es algo que se quedó atrás en los años sesenta, y se ha utilizado con bastante frecuencia para los archivos de configuración en diferentes tipos de programas desde entonces, incluyendo Node, Babel y muchos, muchos otros. -> Más información [en stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Otra curiosidad... qué es un _preset_ ... empecemos por lo que es un plugin de babel: las transformaciones de babel -> se habilitan aplicando plugins, hay un montón de plugins y si tienes que ir añadiendo uno a uno se puede convertir en una pesadilla, -> para hacer esto más fácil, babel ha agrupado conjuntos comunes de plugins en _presets_, por ejemplo @babel-preset-react -> incluye los siguientes plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Es hora de saltar al _webpack.config.js_ - -- Nos podemos asegurar de que tenemos como extension valida _ts_ y _tsx_ -- También que en el loader aceptamos tanto _ts_ como _tsx_ -- Y en el app tenemos como punto de entrada _index.tsx_ - -* Vamos a comprobar que hemos dejado todo funcionando: +- Comprobamos que todo funciona ```bash npm start From 5bb1c2c4c628ea07044f4e0450d7fe757578e09b Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Thu, 28 Aug 2025 07:23:44 +0200 Subject: [PATCH 04/31] refactor list users - react 19 --- .../src => 03-list-users}/index.html | 9 ++-- .../02-base/03-list-users/package.json | 22 ++++++++ .../readme.md | 0 .../readme_es.md | 0 .../src/app.tsx | 0 .../src/index.tsx | 1 + .../src/styles.css | 0 .../02-base/03-list-users/tsconfig.json | 19 +++++++ .../02-base/03-list-users/vite.config.ts | 7 +++ .../01-react/02-base/04-list-users/.babelrc | 7 --- .../02-base/04-list-users/package.json | 39 -------------- .../02-base/04-list-users/tsconfig.json | 18 ------- .../02-base/04-list-users/webpack.config.js | 54 ------------------- 13 files changed, 54 insertions(+), 122 deletions(-) rename 04-frameworks/01-react/02-base/{04-list-users/src => 03-list-users}/index.html (55%) create mode 100644 04-frameworks/01-react/02-base/03-list-users/package.json rename 04-frameworks/01-react/02-base/{04-list-users => 03-list-users}/readme.md (100%) rename 04-frameworks/01-react/02-base/{04-list-users => 03-list-users}/readme_es.md (100%) rename 04-frameworks/01-react/02-base/{04-list-users => 03-list-users}/src/app.tsx (100%) rename 04-frameworks/01-react/02-base/{04-list-users => 03-list-users}/src/index.tsx (90%) rename 04-frameworks/01-react/02-base/{04-list-users => 03-list-users}/src/styles.css (100%) create mode 100644 04-frameworks/01-react/02-base/03-list-users/tsconfig.json create mode 100644 04-frameworks/01-react/02-base/03-list-users/vite.config.ts delete mode 100644 04-frameworks/01-react/02-base/04-list-users/.babelrc delete mode 100644 04-frameworks/01-react/02-base/04-list-users/package.json delete mode 100644 04-frameworks/01-react/02-base/04-list-users/tsconfig.json delete mode 100644 04-frameworks/01-react/02-base/04-list-users/webpack.config.js diff --git a/04-frameworks/01-react/02-base/04-list-users/src/index.html b/04-frameworks/01-react/02-base/03-list-users/index.html similarity index 55% rename from 04-frameworks/01-react/02-base/04-list-users/src/index.html rename to 04-frameworks/01-react/02-base/03-list-users/index.html index a3d74b719..855767d12 100644 --- a/04-frameworks/01-react/02-base/04-list-users/src/index.html +++ b/04-frameworks/01-react/02-base/03-list-users/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + Vite App +
+ diff --git a/04-frameworks/01-react/02-base/03-list-users/package.json b/04-frameworks/01-react/02-base/03-list-users/package.json new file mode 100644 index 000000000..b76d9beec --- /dev/null +++ b/04-frameworks/01-react/02-base/03-list-users/package.json @@ -0,0 +1,22 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + } +} diff --git a/04-frameworks/01-react/02-base/04-list-users/readme.md b/04-frameworks/01-react/02-base/03-list-users/readme.md similarity index 100% rename from 04-frameworks/01-react/02-base/04-list-users/readme.md rename to 04-frameworks/01-react/02-base/03-list-users/readme.md diff --git a/04-frameworks/01-react/02-base/04-list-users/readme_es.md b/04-frameworks/01-react/02-base/03-list-users/readme_es.md similarity index 100% rename from 04-frameworks/01-react/02-base/04-list-users/readme_es.md rename to 04-frameworks/01-react/02-base/03-list-users/readme_es.md diff --git a/04-frameworks/01-react/02-base/04-list-users/src/app.tsx b/04-frameworks/01-react/02-base/03-list-users/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/02-base/04-list-users/src/app.tsx rename to 04-frameworks/01-react/02-base/03-list-users/src/app.tsx diff --git a/04-frameworks/01-react/02-base/04-list-users/src/index.tsx b/04-frameworks/01-react/02-base/03-list-users/src/index.tsx similarity index 90% rename from 04-frameworks/01-react/02-base/04-list-users/src/index.tsx rename to 04-frameworks/01-react/02-base/03-list-users/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/02-base/04-list-users/src/index.tsx +++ b/04-frameworks/01-react/02-base/03-list-users/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/02-base/04-list-users/src/styles.css b/04-frameworks/01-react/02-base/03-list-users/src/styles.css similarity index 100% rename from 04-frameworks/01-react/02-base/04-list-users/src/styles.css rename to 04-frameworks/01-react/02-base/03-list-users/src/styles.css diff --git a/04-frameworks/01-react/02-base/03-list-users/tsconfig.json b/04-frameworks/01-react/02-base/03-list-users/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/02-base/03-list-users/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/02-base/03-list-users/vite.config.ts b/04-frameworks/01-react/02-base/03-list-users/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/02-base/03-list-users/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/02-base/04-list-users/.babelrc b/04-frameworks/01-react/02-base/04-list-users/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/02-base/04-list-users/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/02-base/04-list-users/package.json b/04-frameworks/01-react/02-base/04-list-users/package.json deleted file mode 100644 index 50e9c4ccc..000000000 --- a/04-frameworks/01-react/02-base/04-list-users/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" - } -} diff --git a/04-frameworks/01-react/02-base/04-list-users/tsconfig.json b/04-frameworks/01-react/02-base/04-list-users/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/02-base/04-list-users/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/02-base/04-list-users/webpack.config.js b/04-frameworks/01-react/02-base/04-list-users/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/02-base/04-list-users/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 86964d1312a6fb7d99b8b3f16a6d0b5229481332 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Thu, 28 Aug 2025 08:26:49 +0200 Subject: [PATCH 05/31] update readme --- .../01-react/02-base/02-vite-react/index.html | 2 +- .../01-react/02-base/03-list-users/index.html | 2 +- .../01-react/02-base/03-list-users/readme.md | 20 ++++++++++++++++++- .../02-base/03-list-users/readme_es.md | 20 ++++++++++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/04-frameworks/01-react/02-base/02-vite-react/index.html b/04-frameworks/01-react/02-base/02-vite-react/index.html index 855767d12..050566921 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/index.html +++ b/04-frameworks/01-react/02-base/02-vite-react/index.html @@ -3,7 +3,7 @@ - Vite App + React App diff --git a/04-frameworks/01-react/02-base/03-list-users/index.html b/04-frameworks/01-react/02-base/03-list-users/index.html index 855767d12..050566921 100644 --- a/04-frameworks/01-react/02-base/03-list-users/index.html +++ b/04-frameworks/01-react/02-base/03-list-users/index.html @@ -3,7 +3,7 @@ - Vite App + React App diff --git a/04-frameworks/01-react/02-base/03-list-users/readme.md b/04-frameworks/01-react/02-base/03-list-users/readme.md index 33de240fe..e92e50dd7 100644 --- a/04-frameworks/01-react/02-base/03-list-users/readme.md +++ b/04-frameworks/01-react/02-base/03-list-users/readme.md @@ -2,7 +2,7 @@ ## Summary -This example takes the _03-webpack-react_ example as a starting point. +This example takes the _02-vite-react_ example as a starting point. We're going to ask the Github API for the list of members that belong to an organisation and display it on the screen. @@ -150,6 +150,22 @@ body { } ``` +In order to be able to use our styles, we must import them into our project: + +_./index.tsx_ + +```diff +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; ++ import "./styles.css"; + +const container = document.getElementById("root"); +const root = createRoot(container); + +root.render(); +``` + - And let's integrate it in our app component: _./src/app.tsx_ @@ -228,6 +244,8 @@ _./src/app.tsx_ }, []); ``` +A little bit down the module we will see how react 19 brings a specific hook which is ideal for asynchronous operations like data fetching. + What are we doing here? We are making a call to the Github REST API, this api is asynchronous (hence why we use promises), first we parse the result to _json_ and then we assign that result to the state of our component by by invoking _setMembers_ diff --git a/04-frameworks/01-react/02-base/03-list-users/readme_es.md b/04-frameworks/01-react/02-base/03-list-users/readme_es.md index 6667083aa..b62d9d1ef 100644 --- a/04-frameworks/01-react/02-base/03-list-users/readme_es.md +++ b/04-frameworks/01-react/02-base/03-list-users/readme_es.md @@ -2,7 +2,7 @@ ## Resumen -Este ejemplo toma como punto de partida el ejemplo _03-webpack-react_. +Este ejemplo toma como punto de partida el ejemplo _02-vite-react_. Vamos a pedirle a la API de Github la lista de miembros que pertenece a una organización y vamos a mostrarla por pantalla. @@ -155,6 +155,22 @@ body { } ``` +Para poder usar los estilos tenemos que importarlos dentro de nuestro proyecto: + +_./index.tsx_ + +```diff +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; ++ import "./styles.css"; + +const container = document.getElementById("root"); +const root = createRoot(container); + +root.render(); +``` + - Y vamos a integrarlo en el componente de nuestra aplicación: _./src/app.tsx_ @@ -234,6 +250,8 @@ _./src/app.tsx_ }, []); ``` +Más adelante veremos que React 19 ya trae un hook específico para esto. + ¿Qué estamos haciendo aquí? Estamos haciendo una llamada a la API REST de Github, esta api es asíncrona (de ahí que utlicemos promesas), primero parseamos el resultado a _json_ y después asignamos ese resultado al estado de nuestro componente invocando a _setMembers_ From cb6f6e848923acf15e5c6bb4d0e1c6f39ddc7d8c Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Thu, 28 Aug 2025 08:46:19 +0200 Subject: [PATCH 06/31] refactor react 19 - vite --- .../src => 04-list-refactor}/index.html | 9 ++-- .../02-base/04-list-refactor/package.json | 22 ++++++++ .../readme.md | 2 +- .../readme_es.md | 2 +- .../src/app.tsx | 0 .../src/index.tsx | 1 + .../src/member-table-row.tsx | 0 .../src/member-table.tsx | 0 .../src/model.ts | 0 .../src/styles.css | 0 .../02-base/04-list-refactor/tsconfig.json | 19 +++++++ .../02-base/04-list-refactor/vite.config.ts | 7 +++ .../02-base/05-list-refactor/.babelrc | 7 --- .../02-base/05-list-refactor/package.json | 39 -------------- .../02-base/05-list-refactor/tsconfig.json | 18 ------- .../05-list-refactor/webpack.config.js | 54 ------------------- 16 files changed, 56 insertions(+), 124 deletions(-) rename 04-frameworks/01-react/02-base/{05-list-refactor/src => 04-list-refactor}/index.html (55%) create mode 100644 04-frameworks/01-react/02-base/04-list-refactor/package.json rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/readme.md (98%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/readme_es.md (98%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/app.tsx (100%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/index.tsx (90%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/member-table-row.tsx (100%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/member-table.tsx (100%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/model.ts (100%) rename 04-frameworks/01-react/02-base/{05-list-refactor => 04-list-refactor}/src/styles.css (100%) create mode 100644 04-frameworks/01-react/02-base/04-list-refactor/tsconfig.json create mode 100644 04-frameworks/01-react/02-base/04-list-refactor/vite.config.ts delete mode 100644 04-frameworks/01-react/02-base/05-list-refactor/.babelrc delete mode 100644 04-frameworks/01-react/02-base/05-list-refactor/package.json delete mode 100644 04-frameworks/01-react/02-base/05-list-refactor/tsconfig.json delete mode 100644 04-frameworks/01-react/02-base/05-list-refactor/webpack.config.js diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/index.html b/04-frameworks/01-react/02-base/04-list-refactor/index.html similarity index 55% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/index.html rename to 04-frameworks/01-react/02-base/04-list-refactor/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/02-base/05-list-refactor/src/index.html +++ b/04-frameworks/01-react/02-base/04-list-refactor/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/02-base/04-list-refactor/package.json b/04-frameworks/01-react/02-base/04-list-refactor/package.json new file mode 100644 index 000000000..b76d9beec --- /dev/null +++ b/04-frameworks/01-react/02-base/04-list-refactor/package.json @@ -0,0 +1,22 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + } +} diff --git a/04-frameworks/01-react/02-base/05-list-refactor/readme.md b/04-frameworks/01-react/02-base/04-list-refactor/readme.md similarity index 98% rename from 04-frameworks/01-react/02-base/05-list-refactor/readme.md rename to 04-frameworks/01-react/02-base/04-list-refactor/readme.md index 36c14e9a3..25f0b621b 100644 --- a/04-frameworks/01-react/02-base/05-list-refactor/readme.md +++ b/04-frameworks/01-react/02-base/04-list-refactor/readme.md @@ -2,7 +2,7 @@ ## Summary -This example takes the _04-list-users_ example as a starting point. +This example takes the _03-list-users_ example as a starting point. We will add some refactor to enhance project readiblity and maintalibility. diff --git a/04-frameworks/01-react/02-base/05-list-refactor/readme_es.md b/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md similarity index 98% rename from 04-frameworks/01-react/02-base/05-list-refactor/readme_es.md rename to 04-frameworks/01-react/02-base/04-list-refactor/readme_es.md index 29e7f22fc..586015158 100644 --- a/04-frameworks/01-react/02-base/05-list-refactor/readme_es.md +++ b/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md @@ -2,7 +2,7 @@ ## Resumen -Este ejemplo toma como punto de partida el ejemplo _04-list-users_. +Este ejemplo toma como punto de partida el ejemplo _03-list-users_. ## Paso a Paso diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/app.tsx b/04-frameworks/01-react/02-base/04-list-refactor/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/app.tsx rename to 04-frameworks/01-react/02-base/04-list-refactor/src/app.tsx diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/index.tsx b/04-frameworks/01-react/02-base/04-list-refactor/src/index.tsx similarity index 90% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/index.tsx rename to 04-frameworks/01-react/02-base/04-list-refactor/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/02-base/05-list-refactor/src/index.tsx +++ b/04-frameworks/01-react/02-base/04-list-refactor/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/member-table-row.tsx b/04-frameworks/01-react/02-base/04-list-refactor/src/member-table-row.tsx similarity index 100% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/member-table-row.tsx rename to 04-frameworks/01-react/02-base/04-list-refactor/src/member-table-row.tsx diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/member-table.tsx b/04-frameworks/01-react/02-base/04-list-refactor/src/member-table.tsx similarity index 100% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/member-table.tsx rename to 04-frameworks/01-react/02-base/04-list-refactor/src/member-table.tsx diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/model.ts b/04-frameworks/01-react/02-base/04-list-refactor/src/model.ts similarity index 100% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/model.ts rename to 04-frameworks/01-react/02-base/04-list-refactor/src/model.ts diff --git a/04-frameworks/01-react/02-base/05-list-refactor/src/styles.css b/04-frameworks/01-react/02-base/04-list-refactor/src/styles.css similarity index 100% rename from 04-frameworks/01-react/02-base/05-list-refactor/src/styles.css rename to 04-frameworks/01-react/02-base/04-list-refactor/src/styles.css diff --git a/04-frameworks/01-react/02-base/04-list-refactor/tsconfig.json b/04-frameworks/01-react/02-base/04-list-refactor/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/02-base/04-list-refactor/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/02-base/04-list-refactor/vite.config.ts b/04-frameworks/01-react/02-base/04-list-refactor/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/02-base/04-list-refactor/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/02-base/05-list-refactor/.babelrc b/04-frameworks/01-react/02-base/05-list-refactor/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/02-base/05-list-refactor/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/02-base/05-list-refactor/package.json b/04-frameworks/01-react/02-base/05-list-refactor/package.json deleted file mode 100644 index 50e9c4ccc..000000000 --- a/04-frameworks/01-react/02-base/05-list-refactor/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" - } -} diff --git a/04-frameworks/01-react/02-base/05-list-refactor/tsconfig.json b/04-frameworks/01-react/02-base/05-list-refactor/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/02-base/05-list-refactor/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/02-base/05-list-refactor/webpack.config.js b/04-frameworks/01-react/02-base/05-list-refactor/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/02-base/05-list-refactor/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 32108d9650e29214809d17da5ec0a31d0ef65471 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Thu, 28 Aug 2025 08:49:29 +0200 Subject: [PATCH 07/31] update folder name - cleaning folder --- .../readme_en.md | 0 .../readme_es.md | 0 .../02-base/react-boiler-plate/.gitignore | 24 ------- .../02-base/react-boiler-plate/README.md | 69 ------------------- .../react-boiler-plate/eslint.config.js | 23 ------- .../02-base/react-boiler-plate/index.html | 13 ---- .../02-base/react-boiler-plate/package.json | 30 -------- .../02-base/react-boiler-plate/src/app.tsx | 26 ------- .../02-base/react-boiler-plate/src/main.tsx | 9 --- .../react-boiler-plate/src/vite-env.d.ts | 1 - .../02-base/react-boiler-plate/tsconfig.json | 20 ------ .../02-base/react-boiler-plate/vite.config.ts | 8 --- 12 files changed, 223 deletions(-) rename 04-frameworks/01-react/02-base/{06-list-excercise => 05-list-excercise}/readme_en.md (100%) rename 04-frameworks/01-react/02-base/{06-list-excercise => 05-list-excercise}/readme_es.md (100%) delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/.gitignore delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/README.md delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/index.html delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/package.json delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json delete mode 100644 04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts diff --git a/04-frameworks/01-react/02-base/06-list-excercise/readme_en.md b/04-frameworks/01-react/02-base/05-list-excercise/readme_en.md similarity index 100% rename from 04-frameworks/01-react/02-base/06-list-excercise/readme_en.md rename to 04-frameworks/01-react/02-base/05-list-excercise/readme_en.md diff --git a/04-frameworks/01-react/02-base/06-list-excercise/readme_es.md b/04-frameworks/01-react/02-base/05-list-excercise/readme_es.md similarity index 100% rename from 04-frameworks/01-react/02-base/06-list-excercise/readme_es.md rename to 04-frameworks/01-react/02-base/05-list-excercise/readme_es.md diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore b/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/README.md b/04-frameworks/01-react/02-base/react-boiler-plate/README.md deleted file mode 100644 index 7959ce426..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - ...tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - ...tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - ...tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js b/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js deleted file mode 100644 index d94e7deb7..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { globalIgnores } from 'eslint/config' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]) diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/index.html b/04-frameworks/01-react/02-base/react-boiler-plate/index.html deleted file mode 100644 index 3dcb3bc5b..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Vite + React + TS - - -
- - - diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/package.json b/04-frameworks/01-react/02-base/react-boiler-plate/package.json deleted file mode 100644 index d3b4ff0b0..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "react-boiler-plate", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "react": "^19.1.0", - "react-dom": "^19.1.0" - }, - "devDependencies": { - "@eslint/js": "^9.30.1", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.6.0", - "eslint": "^9.30.1", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "typescript": "~5.8.3", - "typescript-eslint": "^8.35.1", - "vite": "^7.0.4", - "vite-plugin-checker": "^0.10.2" - } -} diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx b/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx deleted file mode 100644 index c50d41a18..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/src/app.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useState } from "react"; - -interface AppProps { - initialCount: number; -} - -export const App: React.FC = ({ initialCount }) => { - const [count, setCount] = useState(initialCount); - - return ( - <> -

Vite + React

-
- -

- Edit src/App.tsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- - ); -}; diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx b/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx deleted file mode 100644 index 2cfa679db..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/src/main.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -createRoot(document.getElementById("root")!).render( - - - -); diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts b/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json b/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json deleted file mode 100644 index 4cd6cb84c..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "esModuleInterop": true, - "isolatedModules": true, - "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], - "module": "ESNext", - "moduleResolution": "bundler", - "noEmit": true, - "noImplicitAny": false, - "noImplicitReturns": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "target": "ESNext", - "useDefineForClassFields": true, - "allowImportingTsExtensions": false - }, - "include": ["src"] -} diff --git a/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts b/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts deleted file mode 100644 index 7273768f9..000000000 --- a/04-frameworks/01-react/02-base/react-boiler-plate/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import checker from "vite-plugin-checker"; - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [react(), checker({ typescript: true })], -}); From cd8d97b785f7dfded527a025d7ccebe24e130c44 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Thu, 28 Aug 2025 19:05:36 +0200 Subject: [PATCH 08/31] previous code sandbox readme - work in progress --- .../01-react/01-previous/readme_es.md | 270 ++++++++---------- 1 file changed, 125 insertions(+), 145 deletions(-) diff --git a/04-frameworks/01-react/01-previous/readme_es.md b/04-frameworks/01-react/01-previous/readme_es.md index f5b2f8b53..97a3369f0 100644 --- a/04-frameworks/01-react/01-previous/readme_es.md +++ b/04-frameworks/01-react/01-previous/readme_es.md @@ -2,184 +2,164 @@ ## Resumen -En este ejemplo vamos a usar _codesandbox_ para crear nuestro primer proyecto en React. +En este ejemplo vamos a crear un _codesandbox_ para entender los primeros conceptos y los motivos principales por los que necesitamos una librería como React. -Puedes encontrar el ejemplo ya implementado en esta URL: https://codesandbox.io/s/strange-tdd-evsp07 +Para ellos nos vamos a abrir un codesandbox de vanilla javascript. El ejemplo terminado ya lo tenéis aquí. -## Paso a paso - -- Codesandbox es una herramienta que nos permite crear proyectos de prueba en React, Angular, Vue, - o TS / ES6 plano trabajando directamente en nuestro navegador web. - -- Si entramos podemos elegir un nuevo proyecto, vamos a seleccionar React + JS. - -- Este proyecto se crea usando una plantilla de _create-react-app_, más adelante sabremos más - sobre este cli, ahora nos vamos a centrar en que estructura tiene una aplicacíon react. - -- Primero vamos a abrir el fichero _index.html_ que se encuentra bajo la carpeta public, - lo más importante que podemos destacar aquí es el siguiente div: - -_./public/index.html_ - -```html -
-``` - -- Ese es el punto de entrada para nuestra aplicación React. - -- React es una librería que no está hecha sólo para correr en un navegador web, la podemos - encontrar también disponible para, por ejemplo, desarrollar aplicaciones móviles con - _react native_. Nos hace falta una librería intermedia que se encarga de conectar - React con un navegador web, esta librería es react-dom. - -- Es hora de abrir el fichero que está en _./src/index.js_ aquí vemos como referenciamos - al div root que hemos creado antes, creamos la raíz de la aplicación y la renderizamos, para ello: +Vamos a intentar crear una aplicación en javascript, muy sencilla, a la que vamos a ir metiéndole poco a poco conceptos básicos. La idea es que al final nos quede algo parecido a React. - - Obtenemos el elemento del dom con el id "root" (el que estaba creado en el HTML principal). - - Creamos la app React en el elemento root. - - Empezamos a pintarla (fijate que le pasamos el componente raíz App) - -> Ojo esta forma de crear la aplicación React es nueva (desde la versión 18), en versiones anteriores -> se usaba _React.render()_ - -_./public/index.js_ +## Paso a paso -```jsx -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; +- Renombramos _index.mjs_ a _index.js_. Renombramos también en el fichero _index.html_. -import App from "./App"; +- Comentamos todo el contenido de _index.js_. -const rootElement = document.getElementById("root"); -const root = createRoot(rootElement); +- En el fichero _index.html_ vamos a renderizar una lista sencilla con datos. -root.render( - - - -); -``` +_index.html_ -> ¿ Qué es React.StrictMode? Es una ayuda para detectar problemas en tiempo de desarrollo, -> detecta si estamos usando ciclos de vida no seguro de componentes, o apis antiguas, -> más información: https://en.reactjs.org/docs/strict-mode.html - -- Ok, acabamos de instanciar un componente que se llama _App_ ¿Donde podemos encontrar esto? - debajo de _./src/App.js_ en este componente lo que hacemos es mostrar dos textos - -```jsx -export default function App() { - return ( -
-

Hello CodeSandbox

-

Start editing to see some magic happen!

-
- ); -} +```diff + + + + JavaScript Sandbox + + + + +-
++
++

Lista de usuarios

++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++
+ + + ``` -Si te fijas es un componente de tipo función, que devuelve un elemento con dos hijos (los dos H1) +Esto funcionará, aunque frameworks como React nos ofrecen un enfoque diferente: permiten manipular o transformar el _index.html_ directamente en el cliente. De esta manera, el servidor no necesita generar un documento completo en cada petición. En su lugar, basta con entregar un _index.html_ básico junto con un archivo JavaScript que, una vez descargado, se encargará de transformar dinámicamente el contenido de la página. -- Vamos a trabajar un poco más sobre este ejemplo, queremos permitir que el usuario teclee - un nombre y mostrar este nombre por pantalla. +Como primer paso vamos a hacer que el contenido de nuestro _index.html_ lo genere el fichero de javascript. Así, dejamos _index.html_ como estaba: -- Primero nos hace falta guardar el nombre que teclea el usuario en una variable que no - desaparezca una vez que se ha ejecutado la función, para ello usaremos _react.useState_. +_index.html_ ```diff -export default function App() { -+ // React.useState returns an array -+ // item[0] is the getter (returns the username) -+ // item[1] is the setter (let us update the state) -+ // That's why we are appliying here destructuring: -+ const [username, setUsername] = React.useState('No name'); -+ - return ( -
-

Hello CodeSandbox

-

Start editing to see some magic happen!

-
- ); -} + + + + JavaScript Sandbox + + + + ++
+-
+-

Lista de usuarios

+-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
+-
+ + + ``` -¿Qué diferencia tiene esto con usar una variable? Si usaramos una variable tal cual -esta se detruiría al terminar la función y se volvería a crear cuando volvieramos a ejecutar -la función, al usar _React.useState_ esta función guarda "en un cajón desastre" el valor que -se estaba editando y lo vuelve a inyectar cuando se vuelve a llamar a la función. +Asignamos a la propiedad `innerHTML` el contenido que queremos renderizar, es decir, la lista: -- Vamos a mostrar el nombre del usuario que está guardado en ese _state_. Esto lo veremos más en - detalle luego, pero abramos boca en este ejemplo, en el código que vemos que parece HTML, - podemos escribir Javascript, ¿Cómo? Encerrandolo entre llaves: +_index.js_ ```diff - return ( -
--

Hello CodeSandbox

-+

{username}

-

Start editing to see some magic happen!

-
- ); ++ import "./styles.css"; + ++ document.getElementById("app").innerHTML = ` ++

Lista de usuarios

++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++ `; ``` -Aquí estamos diciendo en el _h1_, que ejecuta el código javascript que evalua la variable -_username_ +Comprobamos que es el fichero de JavaScript el que me genera el contenido. -- Ahora queremos ir un paso más alla, queremos crear un input que permita al usuario - editar el nombre del usuario, si ponemos algo así como: +Vamos a ir partiendo nuestra lista en partes. Para ello primero segregamos el título: ```diff - return ( -
-

{username}

--

Start editing to see some magic happen!

-+ -
- ); + import "./styles.css"; + ++ const Header = () => { ++ return `

Lista de usuarios

`; ++ }; ++ + document.getElementById("app").innerHTML = ` +-

Lista de usuarios

++ ${Header()} +
1955: Rick Sánchez
+
8765: Beth Harmon
+
7562: Farrokh Bulsara
``` -- Podemos ver como aparece el nombre, pero y si intentamos editar, oye resulta que no se actualiza - esto ¿Por qué? Tenemos que recordar ahora como funcionaba el flujo undireccional, me llegan los - datos, el input dispara un rerender (repintado)y vuelve a leer el del valor de la variable. +A esta función que acabamos de crear, en React, la vamos a llamar componente. Es decir, **en React los componentes son funciones.** Por el momento este componente nos devuelve un trocito de nuestra aplicación, en este caso el título, que renderiza algo en el DOM. -- El input nos expone un evento, _onChange_ que recibe un parametro estandar del _dom_ - accediente a _e.target.value_ tenemos el nuevo valor. +Vamos a seguir rompiendo o componentizando nuestra aplicación en más trocitos. -- Podríamos ahora estar tentados a hacer algo así (OJO esto está mal): +Vamos a crear un componente nuevo que nos devuelva la lista únicamente. ```diff - return ( -
-

{username}

- username = e.target.value} - > -
- ); +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const List = () => { ++ return ` ++
++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++
`; ++ }; + +document.getElementById("app").innerHTML = ` + ${Header()} +-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
++ ${List()} +`; ``` -- ¿Qué pasa con esto? - - - Primero que no debemos de mutar la variable _username_, esa variable - para nosotros es de sólo lectura. - - - Segundo aunque la mutaramos, al volver a repintarse el componente este valor - se pierde. - -- ¿Qué podemos hacer? Utilizar _setUsername_ +Vamos a crear ahora un componente que me renderice en el DOM, cada usuario. Para ello vamos a crear un componente (función) que reciba un objeto usuario con un `id` y un `name`: ```diff - return ( -
-

{username}

- username = e.target.value} -+ onChange={(e) => setUsername(e.target.value)} - > -
- ); +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const User = (props) => { ++ return `
${props.id}: ${props.name}
`; ++ }; + +const List = () => { + return ` +
++ ${User({id: 1955, name 'Rick Sánchez'})} ++ ${User({id: 8765, name 'Beth Harmon'})} ++ ${User({id: 7562, name 'Farrokh Bulsara'})} +-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
+
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; ``` -- ¡ Ahora si que funciona! _setUsername_ se encarga de enviar la petición a un sitio que - seguirá viviendo aunque la función termina, cuando _setState_ se vuelva a invocar - recupera la información y tendremos nuestro dato disponible. +Esos datos que le estamos pasando a la función se les conoce por el nombre de `props`. En React, la sintaxis para ejecutar un componente es muy distinta a esta, la veremos muy pronto. Sin embargo, es muy importante tener en cuenta de que a pesar de que esta sintaxis sea distinta, al final lo que estamos haciendo es invocar funciones y pasarles parámetros de entrada. From e3e918db36478346e7921b43aa30b0b9e95298a5 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Fri, 29 Aug 2025 00:07:26 +0200 Subject: [PATCH 09/31] refactor react concepts --- .../01-react/01-previous/readme_es.md | 166 ++++++++++++++++-- 1 file changed, 148 insertions(+), 18 deletions(-) diff --git a/04-frameworks/01-react/01-previous/readme_es.md b/04-frameworks/01-react/01-previous/readme_es.md index 97a3369f0..9d0145c3f 100644 --- a/04-frameworks/01-react/01-previous/readme_es.md +++ b/04-frameworks/01-react/01-previous/readme_es.md @@ -2,19 +2,16 @@ ## Resumen -En este ejemplo vamos a crear un _codesandbox_ para entender los primeros conceptos y los motivos principales por los que necesitamos una librería como React. +En este ejemplo vamos a crear un _codesandbox_ para entender los primeros conceptos de React y los motivos principales por los que necesitamos una librería como esta. +[Aquí tenéis el ejemplo completo que vamos a desarrollar.](https://codesandbox.io/p/sandbox/react-concepts-rncyq4?file=%2Fsrc%2Findex.js%3A36%2C1) -Para ellos nos vamos a abrir un codesandbox de vanilla javascript. El ejemplo terminado ya lo tenéis aquí. - -Vamos a intentar crear una aplicación en javascript, muy sencilla, a la que vamos a ir metiéndole poco a poco conceptos básicos. La idea es que al final nos quede algo parecido a React. +Para comenzar, partiremos de un proyecto en vanilla JavaScript e iremos añadiendo poco a poco funcionalidades que nos acerquen al enfoque que propone React. El objetivo es ver cómo React resuelve de forma más elegante y potente problemas comunes del desarrollo web. ## Paso a paso -- Renombramos _index.mjs_ a _index.js_. Renombramos también en el fichero _index.html_. - +- Renombramos el archivo _index.mjs_ a _index.js_ y actualizamos la referencia en _index.html_. - Comentamos todo el contenido de _index.js_. - -- En el fichero _index.html_ vamos a renderizar una lista sencilla con datos. +- En el fichero _index.html_ vamos a renderizar de forma estática una lista de usuarios: _index.html_ @@ -39,9 +36,9 @@ _index.html_ ``` -Esto funcionará, aunque frameworks como React nos ofrecen un enfoque diferente: permiten manipular o transformar el _index.html_ directamente en el cliente. De esta manera, el servidor no necesita generar un documento completo en cada petición. En su lugar, basta con entregar un _index.html_ básico junto con un archivo JavaScript que, una vez descargado, se encargará de transformar dinámicamente el contenido de la página. +Esto funciona, pero frameworks como React nos ofrecen un enfoque distinto: permiten transformar dinámicamente el DOM en el cliente. Así, el servidor solo entrega un HTML básico junto con un archivo JavaScript que genera la interfaz. -Como primer paso vamos a hacer que el contenido de nuestro _index.html_ lo genere el fichero de javascript. Así, dejamos _index.html_ como estaba: +Dejamos el HTML vacío y movemos la lista a nuestro archivo _index.js_: _index.html_ @@ -66,9 +63,7 @@ _index.html_ ``` -Asignamos a la propiedad `innerHTML` el contenido que queremos renderizar, es decir, la lista: - -_index.js_ +Yn en _index.js_: ```diff + import "./styles.css"; @@ -81,7 +76,9 @@ _index.js_ + `; ``` -Comprobamos que es el fichero de JavaScript el que me genera el contenido. +Ahora el contenido lo genera JavaScript. Comprobamos que es el fichero de JavaScript el que me genera el contenido. + +### Componentes Vamos a ir partiendo nuestra lista en partes. Para ello primero segregamos el título: @@ -102,9 +99,7 @@ Vamos a ir partiendo nuestra lista en partes. Para ello primero segregamos el t A esta función que acabamos de crear, en React, la vamos a llamar componente. Es decir, **en React los componentes son funciones.** Por el momento este componente nos devuelve un trocito de nuestra aplicación, en este caso el título, que renderiza algo en el DOM. -Vamos a seguir rompiendo o componentizando nuestra aplicación en más trocitos. - -Vamos a crear un componente nuevo que nos devuelva la lista únicamente. +Vamos a seguir rompiendo o componentizando nuestra aplicación. Vamos a crear un componente nuevo que nos devuelva la lista únicamente. ```diff import "./styles.css"; @@ -131,6 +126,8 @@ document.getElementById("app").innerHTML = ` `; ``` +### Props + Vamos a crear ahora un componente que me renderice en el DOM, cada usuario. Para ello vamos a crear un componente (función) que reciba un objeto usuario con un `id` y un `name`: ```diff @@ -162,4 +159,137 @@ document.getElementById("app").innerHTML = ` `; ``` -Esos datos que le estamos pasando a la función se les conoce por el nombre de `props`. En React, la sintaxis para ejecutar un componente es muy distinta a esta, la veremos muy pronto. Sin embargo, es muy importante tener en cuenta de que a pesar de que esta sintaxis sea distinta, al final lo que estamos haciendo es invocar funciones y pasarles parámetros de entrada. +En el argot de react los argumentos de entrada que les pasamos a los componentes se les conoce por el nombre de `props`. Un poco más adelante veremos que además, en React, la sintaxis para ejecutar un componente es muy distinta a ésta. Sin embargo, es muy importante tener presente que a pesar de que esta sintaxis sea distinta, al final lo que estamos haciendo es invocar funciones y pasándoles argumentos de entrada. + +Vamos a acercarnos un poquito más a lo que haría una aplicación real y a simular que los datos que estamos mostrando por la lista nos llegan de una API. Para ello vamos a crearnos un fichero _./api.js_. + +```js +export const getUsers = () => [ + { id: 1955, name: "Rick Sánchez" }, + { id: 8765, name: "Beth Harmon" }, + { id: 7562, name: "Farrokh Bulsara" }, +]; +``` + +Al invocarlo dentro de la función `List` podemos usar directamente un método `map` para poder ejecutar la función `User` por cada uno de los elementos del array, sean los que sean. + +```diff ++ import { getUsers } from './api'; +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const User = (props) => { ++ return `
${props.id}: ${props.name}
`; ++ }; + +const List = () => { ++ const users = getUsers(); + return ` +
++ ${users.map(user=>User(user)).join('')} +- ${User({id: 1955, name 'Rick Sánchez'})} +- ${User({id: 8765, name 'Beth Harmon'})} +- ${User({id: 7562, name 'Farrokh Bulsara'})} +
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; +``` + +En react sin embargo el argumento `props` es un único parámetro, un objeto al que voy a poder pasarle todo lo que quiera. Adaptamos el código. + +```diff +import { getUsers } from "./api"; +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + +- const User = (props) => { ++ const User = ({ user }) => { +- return `
${props.id}: ${props.name}
`; ++ return `
${user.id}: ${user.name}
`; +}; + +const List = () => { + const users = getUsers(); + return ` +
+- ${users.map((user) => User(user)).join("")} ++ ${users.map((user) => User({ user })).join("")} +
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; +``` + +### Reactividad + +Vamos a intentar renderizar por cada elemento un número random, que se calcule en el momento en el que se invoque nuestro componente. + +```diff +const User = ({ user }) => { ++ const randomNumber = Math.random(); +- return `
${user.id}: ${user.name}
`; ++ return `
${user.id}: ${user.name} - ${randomNumber}
`; +}; +``` + +Si lo actualizamos con un setTimeout, vemos que el valor cambia en consola, pero la interfaz no se actualiza: + +```diff +const User = ({ user }) => { +- const randomNumber = Math.random(); ++ let randomNumber = Math.random(); ++ setTimeout(() => { ++ randomNumber = Math.random(); ++ console.log(randomNumber); ++ }, 3000); + return `
${user.id}: ${user.name} - ${randomNumber}
`; +}; +``` + +¿Por qué transcurridos los tres segundos del setTimeout la interfaz de nuestra aplicación no se refresca? Intentad pensar la respuesta... + +La explicación es sencilla: las funciones se ejecutan únicamente una vez. En ese momento devuelven un return que genera un fragmento de HTML. Ese resultado inicial es el que se inyecta en el DOM y no vuelve a cambiar, aunque la lógica interna de la función (como el valor de `randomNumber`) sí se modifique posteriormente. + +Si observamos la consola, veremos que el valor de `randomNumber` efectivamente se recalcula, pero la interfaz no refleja ese cambio. Esto ocurre porque el DOM no está vinculado de manera automática a los datos de nuestra aplicación. + +Y aquí es donde entran en juego librerías como React. Su principal valor es que incorporan reactividad: permiten mantener sincronizados el estado de la aplicación y la interfaz de usuario. + +En React, los estados son la pieza clave para persistir y gestionar datos. Cada vez que un estado cambia, React vuelve a ejecutar los componentes que dependen de él, asegurando que la interfaz se actualice y quede alineada con la información más reciente. + +### Eventos y persistencia + +```diff +const List = () => { +- const users = getUsers(); ++ let users = getUsers(); + ++ const handleClick = () => { ++ alert("button clicked!"); ++ users = [...users, { id: 1234, name: "John Doe" }]; ++ }; + + return ` +
+ ${users.map((user) => User({ user })).join("")} ++ +
`; +}; +``` + +El botón aparece pero al clicar en él, no aparece ni siquiera el alert. ¿Qué está pasando? +De nuevo, cuando `List` se ejecuta, la función `handleClick` se crea. Sin embargo, esa función no se ejecuta hasta que clicamos en el botón y cuando esto ocurre, la función ya no existe, porque la función `List` se ha ejecutado y ha muerto. + +Este es otro de los problemas que va a venir a solucionar React, ya que nos va a permitir, persistir datos, funciones entre ejecución y ejecución de nuestros componentes. From 4c00098428b885d93c9bb2a2a5f1382e636f5ef8 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Fri, 29 Aug 2025 08:48:46 +0200 Subject: [PATCH 10/31] react basic readme --- .../01-previous/{ => 01-concepts}/readme.md | 0 .../{ => 01-concepts}/readme_es.md | 17 ++ .../01-react/01-previous/02-basic/readme.md | 217 ++++++++++++++++++ 3 files changed, 234 insertions(+) rename 04-frameworks/01-react/01-previous/{ => 01-concepts}/readme.md (100%) rename 04-frameworks/01-react/01-previous/{ => 01-concepts}/readme_es.md (96%) create mode 100644 04-frameworks/01-react/01-previous/02-basic/readme.md diff --git a/04-frameworks/01-react/01-previous/readme.md b/04-frameworks/01-react/01-previous/01-concepts/readme.md similarity index 100% rename from 04-frameworks/01-react/01-previous/readme.md rename to 04-frameworks/01-react/01-previous/01-concepts/readme.md diff --git a/04-frameworks/01-react/01-previous/readme_es.md b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md similarity index 96% rename from 04-frameworks/01-react/01-previous/readme_es.md rename to 04-frameworks/01-react/01-previous/01-concepts/readme_es.md index 9d0145c3f..1a48aea24 100644 --- a/04-frameworks/01-react/01-previous/readme_es.md +++ b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md @@ -293,3 +293,20 @@ El botón aparece pero al clicar en él, no aparece ni siquiera el alert. ¿Qué De nuevo, cuando `List` se ejecuta, la función `handleClick` se crea. Sin embargo, esa función no se ejecuta hasta que clicamos en el botón y cuando esto ocurre, la función ya no existe, porque la función `List` se ha ejecutado y ha muerto. Este es otro de los problemas que va a venir a solucionar React, ya que nos va a permitir, persistir datos, funciones entre ejecución y ejecución de nuestros componentes. + +De cara a dejar el ejemplo preparado para el siguiente ejercicio vamos a hacer el siguiente cambio: + +```diff ++ export default function App() { ++ return ` ++ ${Header()} ++ ${List()} ++ `; +} + ++ document.getElementById("app").innerHTML = App(); +- document.getElementById("app").innerHTML = ` +- ${Header()} +- ${List()} +- `; +``` diff --git a/04-frameworks/01-react/01-previous/02-basic/readme.md b/04-frameworks/01-react/01-previous/02-basic/readme.md new file mode 100644 index 000000000..5c92777e1 --- /dev/null +++ b/04-frameworks/01-react/01-previous/02-basic/readme.md @@ -0,0 +1,217 @@ +# 01 Basic - Hola React + +Vamos a migrar el [ejemplo terminado de _01-concepts_](https://codesandbox.io/p/sandbox/strange-tdd-evsp07) a react. Para ello vamos a crearnos un codesandbox de react. + +Creamos el mismo fichero _./api_ + +```js +export const getUsers = () => [ + { id: 1955, name: "Rick Sánchez" }, + { id: 8765, name: "Beth Harmon" }, + { id: 7562, name: "Farrokh Bulsara" }, +]; +``` + +A continuación, desde el ejemplo que hemos dejado preparado en _01-concepts_ vamos a copiar y pegar _index.js_. Vamos a cambiar únicamente lo que devuelve cada uno de los componentes. El motivo es que en react, los componentes devuelven elementos `jsx`, que no es más que azucar sintáctico de javascript. + +**Reemplazamos literales por elementos jsx en los componentes:** + +Por ejemplo, en el componente `Header`: + +- En código Javascript: + +```js +const Header = () => { + return `

Lista de usuarios

`; +}; +``` + +- En código React: + +```jsx +const Header = () => { + return

Lista de usuarios

` +}; +``` + +Si aplicamos el mismo tipo de cambio en el resto de componentes, el fichero _index.jsx_ nos tendría que quedar así: + +```jsx +import React from "react"; +import { getUsers } from "./api"; +import "./styles.css"; + +const Header = () => { + return

Lista de usuarios

; +}; + +const User = ({ user }) => { + let randomNumber = Math.random(); + + setTimeout(() => { + randomNumber = Math.random(); + console.log(randomNumber); + }, 3000); + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; + +const List = () => { + const users = getUsers(); + return
{users.map((user) => User({ user }))}
; +}; + +export default function App() { + return ( +
+ {Header()} + {List()} +
+ ); +} +``` + +Comprobamos que nuestra aplicación renderiza la lista por la pantalla. + +**Sintaxis React** +En React vamos a poder usar la sintaxis jsx cuando invocamos nuestros componentes: + +```diff +export default function App() { + return ( +
++
++ +- {Header()} +- {List()} +
+ ); +} +``` + +Además, si queremos pasar un argumento por props (argumentos de entrada a nuestro componente): + +```diff +const List = () => { + const users = getUsers(); +- return
{users.map((user) => User({ user }))}
; ++ return
{users.map((user) => )}
; +}; +``` + +Al hacer esto, la consola se nos va a lanzar un error que aparece cuando renderizamos elementos iterando por una lista. Como vemos en la traza, nos pide que le pasemos al componente una key con valor único (ya veremos más adelante a que se debe): + +```diff +const List = () => { + const users = getUsers(); +- return
{users.map((user) => )}
; ++ return
{users.map((user) => )}
; +}; +``` + +Pero Como estamos viendo la variable `randomNumber` sigue estando desincronizada de nuestra interfaz de usuario. Esto se debe a que no estamos guardando ese valor en un estado, por lo que react no se entera del cambio. Para que nuestra aplicación sea reactiva hacemos el siguiente cambio: + +```diff +const User = ({ user }) => { +- let randomNumber = Math.random(); ++ const [randomNumber, setRandomNumber] = React.useState(Math.random()) + + +setTimeout(() => { +- randomNumber = Math.random(); ++ setRandomNumber(Math.random()); + console.log(randomNumber); +}, 3000); + + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; +``` + +Si nos fijamos vemos, que a pesar de que es un setTimeout (debería ejecutarse una sola vez), se está ejecutando cada tres segundos ¿Por qué? + +En el código, el setTimeout está dentro del cuerpo del componente. Eso significa que cada vez que el componente se re-ejecuta, React vuelve a crear un nuevo setTimeout. + +Cuando el setTimeout se cumple, llamas a setRandomNumber, lo cual cambia el estado. Ese cambio de estado provoca un nuevo renderizado, y en ese nuevo renderizado se vuelve a crear otro setTimeout. Así entras en un bucle infinito: + +1. ejecución/render → crea setTimeout. +2. setTimeout → randomNumber cambia estado. +3. React detecta cambio de estado → React ejecuta componente de nuevo. +4. Vuelve al paso 1. + +La clave: no es que el setTimeout se repita automáticamente, sino que se vuelve a crear en cada ejecución. + +Cuando escribimos lógica directamente dentro de un componente de React, esa lógica se va a ejecutar en cada renderizado. Esto puede generar problemas de rendimiento o incluso bucles infinitos (como en el caso de setTimeout, que se vuelve a crear en cada render). + +Para controlar cuándo y con qué condiciones se ejecuta cierto código, React nos proporciona el hook `useEffect`, que nos permite manejar efectos secundarios (side effects), como temporizadores, peticiones a APIs o suscripciones a eventos, de forma controlada. + +Su sintaxis es la siguiente: + +```jsx +useEffect(() => { + // 👇 Código (efecto) que quieres ejecutar +}, [dependencias]); +``` + +Parámetros de useEffect: + +- Callback (efecto): la función que queremos ejecutar. +- Lista de dependencias: un array que indica cuándo debe volver a ejecutarse ese callback. + +Ejemplos: + +- [] → el efecto solo se ejecuta una vez, cuando el componente se monta. +- [estado] → el efecto se ejecuta cada vez que cambia estado. +- undefined → el efecto se ejecuta en cada renderizado. (evitar) + +Así, usamos `useEffect` con un array de depencias vacio, porque queremos que el `setTimeout` se ejecute una sola vez, cuando se crea el componente: + +```diff +const User = ({ user }) => { +const [randomNumber, setRandomNumber] = React.useState(Math.random()) + ++ React.useEffect(()=>{ +setTimeout(() => { + setRandomNumber(Math.random()); + console.log(randomNumber); +}, 3000); ++ },[]) + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; +``` + +Vamos a crear ahora un button que al clicar, me añada un nuevo elemento a mi lista: + +```diff +const List = () => { +- const users = getUsers(); ++ Const [users, setUsers] = React.useState(getUsers()); + ++ const handleClick = () => { ++ setUsers([...users, {id: 1234, name: 'John Doe'}]) ++ } + +- return return
{users.map((user) => )}
; ++ return ( ++
++ {users.map((user) => ( ++ ++ ))} ++ ++
++ ); +}; +``` From a4ed3f261ce29bd69d161fdc7707ac545c2626ed Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Fri, 29 Aug 2025 12:49:19 +0200 Subject: [PATCH 11/31] update with codesandbox links --- .../01-react/01-previous/01-concepts/readme_es.md | 2 +- 04-frameworks/01-react/01-previous/02-basic/readme.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/04-frameworks/01-react/01-previous/01-concepts/readme_es.md b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md index 1a48aea24..2f03fd513 100644 --- a/04-frameworks/01-react/01-previous/01-concepts/readme_es.md +++ b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md @@ -3,7 +3,7 @@ ## Resumen En este ejemplo vamos a crear un _codesandbox_ para entender los primeros conceptos de React y los motivos principales por los que necesitamos una librería como esta. -[Aquí tenéis el ejemplo completo que vamos a desarrollar.](https://codesandbox.io/p/sandbox/react-concepts-rncyq4?file=%2Fsrc%2Findex.js%3A36%2C1) +[Aquí tenéis el ejemplo completo que vamos a desarrollar.](https://codesandbox.io/p/sandbox/react-concepts-rncyq4) Para comenzar, partiremos de un proyecto en vanilla JavaScript e iremos añadiendo poco a poco funcionalidades que nos acerquen al enfoque que propone React. El objetivo es ver cómo React resuelve de forma más elegante y potente problemas comunes del desarrollo web. diff --git a/04-frameworks/01-react/01-previous/02-basic/readme.md b/04-frameworks/01-react/01-previous/02-basic/readme.md index 5c92777e1..42351d280 100644 --- a/04-frameworks/01-react/01-previous/02-basic/readme.md +++ b/04-frameworks/01-react/01-previous/02-basic/readme.md @@ -1,6 +1,6 @@ # 01 Basic - Hola React -Vamos a migrar el [ejemplo terminado de _01-concepts_](https://codesandbox.io/p/sandbox/strange-tdd-evsp07) a react. Para ello vamos a crearnos un codesandbox de react. +Vamos a migrar la aplicación en Javascript de _01-concepts_ a react. [Aquí tenéis el ejemplo completo que vamos a desarrollar](https://codesandbox.io/p/sandbox/react-basic-h9rhkk) Para ello vamos a crearnos un codesandbox de react. Creamos el mismo fichero _./api_ @@ -103,7 +103,7 @@ const List = () => { }; ``` -Al hacer esto, la consola se nos va a lanzar un error que aparece cuando renderizamos elementos iterando por una lista. Como vemos en la traza, nos pide que le pasemos al componente una key con valor único (ya veremos más adelante a que se debe): +Al hacer esto, la consola nos va a lanzar un error que aparece cuando renderizamos elementos iterando por una lista. Como vemos en la traza, nos pide que le pasemos al componente una key con valor único (ya veremos más adelante a que se debe): ```diff const List = () => { @@ -140,7 +140,7 @@ Si nos fijamos vemos, que a pesar de que es un setTimeout (debería ejecutarse u En el código, el setTimeout está dentro del cuerpo del componente. Eso significa que cada vez que el componente se re-ejecuta, React vuelve a crear un nuevo setTimeout. -Cuando el setTimeout se cumple, llamas a setRandomNumber, lo cual cambia el estado. Ese cambio de estado provoca un nuevo renderizado, y en ese nuevo renderizado se vuelve a crear otro setTimeout. Así entras en un bucle infinito: +Cuando el setTimeout se cumple, llama a setRandomNumber, lo cual cambia el estado. Ese cambio de estado provoca un nuevo renderizado, y en ese nuevo renderizado se vuelve a crear otro setTimeout. Así entras en un bucle infinito: 1. ejecución/render → crea setTimeout. 2. setTimeout → randomNumber cambia estado. @@ -193,7 +193,7 @@ setTimeout(() => { }; ``` -Vamos a crear ahora un button que al clicar, me añada un nuevo elemento a mi lista: +Vamos a crear ahora un button que al clicar, me añada un nuevo elemento a la lista: ```diff const List = () => { From ff6b536f6ae431d95041299136ea10a7f7f0bbf9 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Fri, 29 Aug 2025 15:26:38 +0200 Subject: [PATCH 12/31] refactor react 19 - vite --- .../03-react-hooks/00-boilerplate/.babelrc | 7 - .../03-react-hooks/00-boilerplate/Readme.md | 132 ++---------------- .../00-boilerplate/Readme_es.md | 126 ++--------------- .../00-boilerplate/{src => }/index.html | 8 +- .../00-boilerplate/package.json | 44 ++---- .../03-react-hooks/00-boilerplate/src/app.tsx | 5 - .../00-boilerplate/src/index.ts | 1 + .../00-boilerplate/src/index.tsx | 8 -- .../00-boilerplate/src/styles.css | 3 - .../00-boilerplate/tsconfig.json | 24 ++-- .../00-boilerplate/vite.config.ts | 6 + .../00-boilerplate/webpack.config.js | 54 ------- 12 files changed, 64 insertions(+), 354 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/.babelrc rename 04-frameworks/01-react/03-react-hooks/00-boilerplate/{src => }/index.html (55%) delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/styles.css create mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/.babelrc b/04-frameworks/01-react/03-react-hooks/00-boilerplate/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md index 1afae0061..bf1aaebfc 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md @@ -1,125 +1,23 @@ -# 03 Webpack React +## 02 Web Boiler plate ## Summary -This example takes the _02-webpack-boiler_ example as a starting point. - -We will go step by step adding the necessary configuration so that we integrate -**React** into our build process. - -# Step by Step guide - -- First we copy the previous example, and do a _npm install_ - -```bash -npm install -``` - -- Let's install _react_ and _react-dom_ - -```bash -npm install react react-dom --save -``` - -- Let's install _react_ and _react-dom_ typings - -```bash -npm install @types/react @types/react-dom --save-dev -``` - -This way we have the React library and the bindings to integrate with a web browser. - -- In the index.html we are going to put the _div_ that will serve as entry point to instantiate our React application. our React application. - -_./src/index.html_ - -```diff - --

Hello World !

-+
- -``` - -- Let's create our first React component. - -_./src/app.tsx_ - -```tsx -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; -``` - -- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _ReactDOM.render_. - -_./src/index.tsx_ - -```tsx -import React from "react"; -import ReactDOM from "react-dom"; -import { App } from "./app"; - -ReactDOM.render( -
- -
, - document.getElementById("root") -); -``` - -- We are on the right track, but if we try to run this it will fail, since _babel_ does not know how to transform the _jsx_ (remember that this was a sugar, which was actually an XML) into javaScript, in order for babel to be able to understand this we have to install the _preset_ _@babel/preset-react_ - -First we install it and the configure it. - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> By the way the _rc_ suffix is pretty usual in linux it's stands for "runcom" -> (CTSS system 1962-63) Script file containing startup instructions for an application program. -> In other words, "rc" is just something that stuck from back in the sixties, and has been used quite often for configuration files in different sorts of programs since, including Node, Babel and many, many others. -> More info [on stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Another curiosity... what is a _preset_ ... let's start with what is a babel plugin: babel transformations are -> enabled by applying plugins, there are plenty of plugins and if you have to go adding one by one it can become a nightmare, -> in order to make this easier, babel has grouped common sets of plugins in _presets_, for instance @babel-preset-react -> includes the following plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Is time to double check the _webpack.config.js_ - -- We can make sure that we have _ts_ and _tsx_ as valid extensions. -- Also that in the loader we accept both _ts_ and _tsx_. -- And in the app we have as entry point _index.tsx_. - -* Let's check that things are working as expected: - -```bash -npm start -``` - - - - +In this example there is a vite boiler plate set up with Typescript support, just in the step before +to adding React support. +It is based on the Vite examples. +This example is the only one that doesn't have a step-by-step (if you need guidance, you can go to the +vite examples you'll find in this repository). +Highlights: +- Added TypeScript as a local dev dependency. +- Switched project to use ES Modules in package.json. +- Created a `tsconfig.json` with a minimal configuration. +- Vite uses esbuild for transpilation (fast, no type checking). +- Enabled `isolatedModules` and `useDefineForClassFields` for `esbuild`compatibility. +- Type checking is handled separately (via tsc or IDE). +In the following example we will take this as a starting point and we will go step by step adding +support for React. diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md index bb34f2812..f8eeb987b 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md @@ -1,119 +1,23 @@ -# 03 Webpack React +## 02 Web Boiler plate ## Resumen -Este ejemplo toma como punto de partida el ejemplo _02-webpack-boiler_. +En este ejemplo desarrollamos un boilerplate de Vite configurado con soporte para TypeScript, justo en el paso previo +a añadir soporte para React. -Vamos a ir paso a paso añdiendo la configuración necesaria para que integrar -**React** en nuestro proceso de build. +Está basado en los ejemplos de Vite. -## Paso a Paso +Este ejemplo es el único que no tiene una guía paso a paso (si necesitas orientación, puedes consultar los +ejemplos de Vite que encontrarás en este repositorio). -- Primero copiamos el ejemplo anterior, y hacemos un _npm install_ +Puntos destacados: -```bash -npm install -``` +- Se agregó TypeScript como dependencia de desarrollo local. +- Se cambió el proyecto para usar ES Modules `package.json`. +- Se creó un `tsconfig.json` con una configuración mínima. +- Vite utiliza esbuild para la transpilación (rápido, sin comprobación de tipos). +- Se habilitó `isolatedModules` y `useDefineForClassFields` para que sea compatible con `esbuild`. +- La comprobación de tipos se maneja por separado (a través de tsc o del IDE). -- Vamos a instalar _react_ y _react-dom_ - -```bash -npm install react react-dom --save -``` - -- Vamos a instalarnos los typing de _react_ y _react-dom_ - -```bash -npm install @types/react @types/react-dom --save-dev -``` - -Así tenemos la librería de React y los bindings para que se integre con un navegador web. - -- En el index.html vamos a meter el _div_ que nos servirá como punto de entrada para instanciar - nuestra aplicación React. - -_./src/index.html_ - -```diff - --

Hello World !

-+
- -``` - -- Vamos a crear nuestro primero componente React. - -_./src/app.tsx_ - -```tsx -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; -``` - -- Es hora de instanciar ese compente principal, para poder integrarlo con el navegador - tenemos que hacer uso a _ReactDOM.render_ - -_./src/index.tsx_ - -```tsx -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -const container = document.getElementById("root"); -const root = createRoot(container); - -root.render(); -``` - -- Vamos por buen camino, pero si intentamos ejecutar esto no va fallar, ya que _babel_ no sabe - como transformar el _jsx_ (recordemos que esto era un azúcar, que en realidad era un XML) a - javaScript, para que babel sea capaz de entender esto tenemos que instalar el _preset_ - _@babel/preset-react_ - -Primero lo instalamos - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> Por cierto, el sufijo _rc_ es bastante habitual en linux, significa "runcom". -> (Sistema CTSS 1962-63) Archivo de script que contiene instrucciones de inicio para un programa de aplicación. -> En otras palabras, "rc" es algo que se quedó atrás en los años sesenta, y se ha utilizado con bastante frecuencia para los archivos de configuración en diferentes tipos de programas desde entonces, incluyendo Node, Babel y muchos, muchos otros. -> Más información [en stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Otra curiosidad... qué es un _preset_ ... empecemos por lo que es un plugin de babel: las transformaciones de babel -> se habilitan aplicando plugins, hay un montón de plugins y si tienes que ir añadiendo uno a uno se puede convertir en una pesadilla, -> para hacer esto más fácil, babel ha agrupado conjuntos comunes de plugins en _presets_, por ejemplo @babel-preset-react -> incluye los siguientes plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Es hora de saltar al _webpack.config.js_ - -- Nos podemos asegurar de que tenemos como extension valida _ts_ y _tsx_ -- También que en el loader aceptamos tanto _ts_ como _tsx_ -- Y en el app tenemos como punto de entrada _index.tsx_ - -* Vamos a comprobar que hemos dejado todo funcionando: - -```bash -npm start -``` +En el siguiente ejemplo tomaremos este como punto de partida y, paso a paso, añadiremos +soporte para React. diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.html b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.html rename to 04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html index a3d74b719..dd5f1546a 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html @@ -1,12 +1,12 @@ - - - - My App Example + + +
+ diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json index 50e9c4ccc..964563240 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json @@ -1,39 +1,17 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" } } diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx deleted file mode 100644 index f732c856e..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts new file mode 100644 index 000000000..f69b4850f --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts @@ -0,0 +1 @@ +console.log("Vite-boiler-plate"); diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx deleted file mode 100644 index 7e439b87e..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -const container = document.getElementById("root"); -const root = createRoot(container); - -root.render(); diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/styles.css b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/styles.css deleted file mode 100644 index 74dc08fbb..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.my-text { - color: blue; -} diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json index 3312b5f1e..6414575cc 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json @@ -1,18 +1,18 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts b/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts new file mode 100644 index 000000000..5bfe487c0 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; + +export default defineConfig({ + plugins: [checker({ typescript: true })], +}); diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/webpack.config.js b/04-frameworks/01-react/03-react-hooks/00-boilerplate/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From cca77ae4d92ecb0d5d262e7e55ff3393e890c639 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Fri, 29 Aug 2025 15:52:04 +0200 Subject: [PATCH 13/31] refactor react 19 - vite - useState hook --- .../03-react-hooks/00-boilerplate/index.html | 3 +- .../00-boilerplate/package.json | 5 ++ .../00-boilerplate/tsconfig.json | 1 + .../00-boilerplate/vite.config.ts | 3 +- .../03-react-hooks/01-use-state/.babelrc | 7 --- .../01-use-state/{src => }/index.html | 9 ++-- .../03-react-hooks/01-use-state/package.json | 45 +++++----------- .../03-react-hooks/01-use-state/tsconfig.json | 25 ++++----- .../01-use-state/vite.config.ts | 7 +++ .../01-use-state/webpack.config.js | 54 ------------------- 10 files changed, 49 insertions(+), 110 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/01-use-state/.babelrc rename 04-frameworks/01-react/03-react-hooks/01-use-state/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/01-use-state/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/01-use-state/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html index dd5f1546a..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html @@ -3,10 +3,11 @@ + React App
- + diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json index 964563240..b76d9beec 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json @@ -9,9 +9,14 @@ "preview": "vite preview" }, "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", "tslib": "^2.8.1", "typescript": "^5.9.2", "vite": "^7.1.3", "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" } } diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json index 6414575cc..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "esModuleInterop": true, "isolatedModules": true, + "jsx": "react-jsx", "lib": ["ESNext", "DOM"], "module": "ESNext", "moduleResolution": "bundler", diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts b/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts index 5bfe487c0..a0024d88e 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from "vite"; import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; export default defineConfig({ - plugins: [checker({ typescript: true })], + plugins: [checker({ typescript: true }), react()], }); diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/.babelrc b/04-frameworks/01-react/03-react-hooks/01-use-state/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html b/04-frameworks/01-react/03-react-hooks/01-use-state/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html rename to 04-frameworks/01-react/03-react-hooks/01-use-state/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/package.json b/04-frameworks/01-react/03-react-hooks/01-use-state/package.json index 50e9c4ccc..b76d9beec 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/package.json +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/package.json @@ -1,39 +1,22 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^19.1.1", + "react-dom": "^19.1.1" } } diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/tsconfig.json b/04-frameworks/01-react/03-react-hooks/01-use-state/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/vite.config.ts b/04-frameworks/01-react/03-react-hooks/01-use-state/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/webpack.config.js b/04-frameworks/01-react/03-react-hooks/01-use-state/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 1ea77384ebc6597348bcb378aba5c1a0e0c29e99 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 07:50:21 +0200 Subject: [PATCH 14/31] refactor react 19 - vite - useState hook object --- .../02-use-state-object/.babelrc | 7 --- .../02-use-state-object/{src => }/index.html | 9 ++-- .../02-use-state-object/package.json | 45 +++++----------- .../02-use-state-object/src/demo.tsx | 9 ++++ .../02-use-state-object/tsconfig.json | 25 ++++----- .../02-use-state-object/vite.config.ts | 7 +++ .../02-use-state-object/webpack.config.js | 54 ------------------- 7 files changed, 48 insertions(+), 108 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/02-use-state-object/.babelrc rename 04-frameworks/01-react/03-react-hooks/02-use-state-object/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/02-use-state-object/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/02-use-state-object/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/.babelrc b/04-frameworks/01-react/03-react-hooks/02-use-state-object/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/index.html b/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/02-use-state-object/src/index.html rename to 04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json b/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json index 50e9c4ccc..b76d9beec 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json @@ -1,39 +1,22 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^19.1.1", + "react-dom": "^19.1.1" } } diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/demo.tsx index d4ca6be9a..983a5fdfa 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/demo.tsx +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/src/demo.tsx @@ -25,6 +25,15 @@ export const MyComponent: React.FC = () => { }) } /> + + setUserInfo({ + ...userInfo, + lastname: e.target.value, + }) + } + /> ); }; diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/tsconfig.json b/04-frameworks/01-react/03-react-hooks/02-use-state-object/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/vite.config.ts b/04-frameworks/01-react/03-react-hooks/02-use-state-object/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/webpack.config.js b/04-frameworks/01-react/03-react-hooks/02-use-state-object/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From d73bb9da1938f8e7378fb40b8c4ddbaa8eba8189 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 09:09:29 +0200 Subject: [PATCH 15/31] refactor react 19 - vite - useEffect hook --- .../03-component-did-onload/.babelrc | 7 --- .../03-component-did-onload/package.json | 39 -------------- .../03-component-did-onload/tsconfig.json | 18 ------- .../03-component-did-onload/webpack.config.js | 54 ------------------- .../Readme.md | 0 .../03-component-mount/index.html | 13 +++++ .../03-component-mount/package.json | 22 ++++++++ .../readme_es.md | 0 .../src/app.tsx | 0 .../src/demo.tsx | 0 .../src/index.html | 0 .../src/index.tsx | 0 .../src/styles.css | 0 .../03-component-mount/tsconfig.json | 19 +++++++ .../03-component-mount/vite.config.ts | 7 +++ .../Readme.md | 2 +- .../Readme_es.md | 2 +- .../04-component-unmount/index.html | 13 +++++ .../04-component-unmount/package.json | 22 ++++++++ .../src/app.tsx | 0 .../04-component-unmount/src/demo.tsx | 42 +++++++++++++++ .../src/index.html | 0 .../src/index.tsx | 0 .../src/styles.css | 0 .../04-component-unmount/tsconfig.json | 19 +++++++ .../04-component-unmount/vite.config.ts | 7 +++ .../04-component_unmount/.babelrc | 7 --- .../04-component_unmount/package.json | 39 -------------- .../04-component_unmount/src/demo.tsx | 24 --------- .../04-component_unmount/tsconfig.json | 18 ------- .../04-component_unmount/webpack.config.js | 54 ------------------- .../05-component-update-render/Readme.md | 2 +- .../05-component-update-render/Readme_es.md | 2 +- 33 files changed, 168 insertions(+), 264 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/03-component-did-onload/.babelrc delete mode 100644 04-frameworks/01-react/03-react-hooks/03-component-did-onload/package.json delete mode 100644 04-frameworks/01-react/03-react-hooks/03-component-did-onload/tsconfig.json delete mode 100644 04-frameworks/01-react/03-react-hooks/03-component-did-onload/webpack.config.js rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/Readme.md (100%) create mode 100644 04-frameworks/01-react/03-react-hooks/03-component-mount/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/03-component-mount/package.json rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/readme_es.md (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/src/app.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/src/demo.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/src/index.html (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/src/index.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 03-component-mount}/src/styles.css (100%) create mode 100644 04-frameworks/01-react/03-react-hooks/03-component-mount/tsconfig.json create mode 100644 04-frameworks/01-react/03-react-hooks/03-component-mount/vite.config.ts rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/Readme.md (97%) rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/Readme_es.md (99%) create mode 100644 04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/src/app.tsx (100%) create mode 100644 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/demo.tsx rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/src/index.html (100%) rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/src/index.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/src/styles.css (100%) create mode 100644 04-frameworks/01-react/03-react-hooks/04-component-unmount/tsconfig.json create mode 100644 04-frameworks/01-react/03-react-hooks/04-component-unmount/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/.babelrc delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/package.json delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/demo.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/tsconfig.json delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/.babelrc b/04-frameworks/01-react/03-react-hooks/03-component-did-onload/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/package.json b/04-frameworks/01-react/03-react-hooks/03-component-did-onload/package.json deleted file mode 100644 index 50e9c4ccc..000000000 --- a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" - } -} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/tsconfig.json b/04-frameworks/01-react/03-react-hooks/03-component-did-onload/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/webpack.config.js b/04-frameworks/01-react/03-react-hooks/03-component-did-onload/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/Readme.md b/04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/Readme.md rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html b/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json b/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json new file mode 100644 index 000000000..b76d9beec --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json @@ -0,0 +1,22 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + } +} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/readme_es.md b/04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/readme_es.md rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/app.tsx b/04-frameworks/01-react/03-react-hooks/03-component-mount/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/app.tsx rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/src/app.tsx diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/03-component-mount/src/demo.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/demo.tsx rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/src/demo.tsx diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/index.html b/04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.html similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/index.html rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.html diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/index.tsx b/04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/index.tsx rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.tsx diff --git a/04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/styles.css b/04-frameworks/01-react/03-react-hooks/03-component-mount/src/styles.css similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/03-component-did-onload/src/styles.css rename to 04-frameworks/01-react/03-react-hooks/03-component-mount/src/styles.css diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/tsconfig.json b/04-frameworks/01-react/03-react-hooks/03-component-mount/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/vite.config.ts b/04-frameworks/01-react/03-react-hooks/03-component-mount/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme.md b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md similarity index 97% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme.md rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md index bdda788ad..4ff9123bb 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md @@ -2,7 +2,7 @@ ## Resume -This example takes the _03-component-dom-onload_ example as starting point. +This example takes the _03-component-mount_ example as starting point. In this example we are going to see how to free resources when we unmount a DOM component. diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme_es.md b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md similarity index 99% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme_es.md rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md index be29ee2ad..fdfdd3e33 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md @@ -2,7 +2,7 @@ ## Resumen -Este ejemplo toma como punto de partida el ejemplo _03-component-dom-onload_. +Este ejemplo toma como punto de partida el ejemplo _03-component-mount_. En este ejemplo vamos a ver como liberar recursos cuando desmontamos un componente del DOM. diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html b/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json b/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json new file mode 100644 index 000000000..b76d9beec --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json @@ -0,0 +1,22 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + } +} diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/app.tsx b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/app.tsx rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/app.tsx diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/demo.tsx new file mode 100644 index 000000000..622ae6765 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/demo.tsx @@ -0,0 +1,42 @@ +import React from "react"; + +export const MyChildComponent = () => { + const [count, setCount] = React.useState(0); + + React.useEffect(() => { + console.log("Componente se monta"); + return () => console.log("Componente se desmonta"); + }, []); + + React.useEffect(() => { + console.log("body - count just changed", count); + return () => + console.log("cleanupFunction - count is about to change", count); + }, [count]); + + return ( + <> +

Count is {count}

+ + + ); +}; + +export const MyComponent = () => { + const [visible, setVisible] = React.useState(false); + + return ( + <> + + {visible && } + + ); +}; diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.html b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.html similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.html rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.html diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.tsx b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.tsx rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.tsx diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/styles.css b/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/styles.css similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/styles.css rename to 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/styles.css diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/tsconfig.json b/04-frameworks/01-react/03-react-hooks/04-component-unmount/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/vite.config.ts b/04-frameworks/01-react/03-react-hooks/04-component-unmount/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/.babelrc b/04-frameworks/01-react/03-react-hooks/04-component_unmount/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/package.json b/04-frameworks/01-react/03-react-hooks/04-component_unmount/package.json deleted file mode 100644 index 50e9c4ccc..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" - } -} diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/demo.tsx deleted file mode 100644 index f57ca7bf4..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/demo.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; - -export const MyChildComponent = () => { - React.useEffect(() => { - console.log("El componente se acaba de montar en el DOM"); - - return () => console.log("El componente se acaba de desmontar del DOM"); - }, []); - - return

Hello form child component

; -}; - -export const MyComponent = () => { - const [visible, setVisible] = React.useState(false); - - return ( - <> - {visible && } - - - ); -}; diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/tsconfig.json b/04-frameworks/01-react/03-react-hooks/04-component_unmount/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/03-react-hooks/04-component_unmount/webpack.config.js b/04-frameworks/01-react/03-react-hooks/04-component_unmount/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md index 567548c0a..2540f5ac7 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md @@ -2,7 +2,7 @@ ## Resume -We will take as starting point sample \_04-component-dom-unmount. +We will take as starting point sample \_04-component-unmount. In this example we will check how to use React.useEffect in order to execute a given code right after each render. diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md index 3055849a7..4b10f8314 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md @@ -2,7 +2,7 @@ ## Resumen -Este ejemplo toma como punto de partida el ejemplo \_04-component-dom-unmount. +Este ejemplo toma como punto de partida el ejemplo \_04-component-unmount. En este ejemplo vamos a ver como usar React.useEffect para ejecutar un código justo después de cada renderizado. From a972bc780d911515da5c6da74b798c10984f9c93 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 12:19:38 +0200 Subject: [PATCH 16/31] refactor react 19 - vite - useEffect hook --- .../04-component-unmount/Readme_es.md | 6 +-- .../05-component-update-render/.babelrc | 7 --- .../05-component-update-render/Readme_es.md | 51 +++++++++++++++++- .../05-component-update-render/index.html | 13 +++++ .../05-component-update-render/package.json | 45 +++++----------- .../05-component-update-render/src/demo.tsx | 18 +++++-- .../05-component-update-render/tsconfig.json | 25 ++++----- .../05-component-update-render/vite.config.ts | 7 +++ .../webpack.config.js | 54 ------------------- .../06-ajax-field-change/.babelrc | 7 --- .../06-ajax-field-change/package.json | 40 -------------- .../06-ajax-field-change/tsconfig.json | 18 ------- .../06-ajax-field-change/webpack.config.js | 54 ------------------- 13 files changed, 114 insertions(+), 231 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/.babelrc create mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/.babelrc delete mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json delete mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json delete mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md index fdfdd3e33..de91a6c03 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md @@ -39,10 +39,10 @@ _./src/demo.tsx_ ```diff return ( <> - {visible &&

Hello

} + + {visible &&

Hello

} ); ``` @@ -61,11 +61,11 @@ export const MyComponent = () => { return ( <> -- {visible &&

Hello

} -+ {visible && } +- {visible &&

Hello

} ++ {visible && } ); }; diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/.babelrc b/04-frameworks/01-react/03-react-hooks/05-component-update-render/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md index 4b10f8314..3b0ca39e3 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md @@ -26,10 +26,10 @@ export const MyComponent = () => { return ( <> - {visible && } + {visible && } ); }; @@ -93,6 +93,55 @@ React.useEffect(() => { - Si ejecutamos podemos ver como se invocan las dos funciones. +Como hemos visto, si no pasamos un segundo argumento a _useEffect_, el effect o callback que pasamos por primer parámetro se ejecutará en cada re-ejecución. Sin embargo, si queremos controlar cuándo se ejecuta el efecto y su función de limpieza, debemos indicar explícitamente las dependencias en el segundo parámetro. + +Para comprobar este comportamiento, eliminamos el useEffect del ejemplo anterior y creamos uno nuevo que se dispare cada vez que cambie cualquier valor dentro de _userInfo_: + +```diff +const MyChildComponent = () => { + const [userInfo, setUserInfo] = React.useState({ + name: "John", + lastname: "Doe" + }); + +- React.useEffect(() => { +- console.log("A. Called right after every render"); +- return () => console.log("B. Cleanup function called after every render"); +- }); + ++ React.useEffect(() => { ++ console.log("Effect ran: component rendered with userInfo:", userInfo); ++ return () => ++ console.log("Cleanup before running new effect, userInfo was", userInfo); ++ }, [userInfo]); +``` + +Independientemente de qué propiedad modifiquemos, el efecto y su función de limpieza se ejecutarán. Esto ocurre porque hemos definido como dependencia al estado completo _userInfo_. + +Si queremos diferenciar la ejecución del efecto en función de propiedades concretas, basta con especificar directamente la propiedad dentro del array de dependencias: + +```diff +const MyChildComponent = () => { + const [userInfo, setUserInfo] = React.useState({ + name: "John", + lastname: "Doe" + }); + + React.useEffect(() => { +- console.log("Effect ran: component rendered with userInfo:", userInfo); ++ console.log(`Effect ran: component rendered with name: ${userInfo.name}`); ++ return () => +- console.log("Cleanup before running new effect, userInfo was", userInfo); ++ console.log(`Cleanup before running new effect, name: ${userInfo.name}`); ++ }, [userInfo.name]); + ++ React.useEffect(() => { ++ console.log(`Effect ran: component rendered with lastname: ${userInfo.lastname}`); ++ return () => ++ console.log(`Cleanup before running new effect, lastname: ${userInfo.lastname}`); ++ }, [userInfo.lastname]); +``` + ```bash npm start ``` diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html b/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json b/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json index 50e9c4ccc..b76d9beec 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json @@ -1,39 +1,22 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@vitejs/plugin-react": "^5.0.1", + "tslib": "^2.8.1", + "typescript": "^5.9.2", + "vite": "^7.1.3", + "vite-plugin-checker": "^0.10.2" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^19.1.1", + "react-dom": "^19.1.1" } } diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/demo.tsx index a346bfe9a..b0d80ae6b 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/demo.tsx +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/demo.tsx @@ -5,10 +5,10 @@ export const MyComponent = () => { return ( <> - {visible && } + {visible && } ); }; @@ -20,10 +20,20 @@ const MyChildComponent = () => { }); React.useEffect(() => { - console.log("A. Called right after every render"); + console.log(`Effect ran: component rendered with name: ${userInfo.name}`); + return () => + console.log(`Cleanup before running new effect, name: ${userInfo.name}`); + }, [userInfo.name]); - return () => console.log("B. Cleanup function called after every render"); - }); + React.useEffect(() => { + console.log( + `Effect ran: component rendered with lastname: ${userInfo.lastname}` + ); + return () => + console.log( + `Cleanup before running new effect, lastname: ${userInfo.lastname}` + ); + }, [userInfo.lastname]); return (
diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/tsconfig.json b/04-frameworks/01-react/03-react-hooks/05-component-update-render/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/vite.config.ts b/04-frameworks/01-react/03-react-hooks/05-component-update-render/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/webpack.config.js b/04-frameworks/01-react/03-react-hooks/05-component-update-render/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/.babelrc b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json deleted file mode 100644 index d434b896c..000000000 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" - }, - "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" - } -} diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json deleted file mode 100644 index 3312b5f1e..000000000 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, - "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -} diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/webpack.config.js b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From c0b546951b9d7769959ae70c230247ae4a24f471 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 14:34:13 +0200 Subject: [PATCH 17/31] add missing react and react-dom types --- .../01-react/02-base/01-vite-boiler/package.json | 1 - .../01-react/02-base/02-vite-react/package.json | 15 ++++++++------- .../01-react/02-base/02-vite-react/readme.md | 6 ++++++ .../01-react/02-base/02-vite-react/readme_es.md | 6 ++++++ .../01-react/02-base/03-list-users/package.json | 15 ++++++++------- .../02-base/04-list-refactor/package.json | 15 ++++++++------- .../03-react-hooks/00-boilerplate/package.json | 15 ++++++++------- .../03-react-hooks/01-use-state/package.json | 15 ++++++++------- .../02-use-state-object/package.json | 15 ++++++++------- .../03-component-mount/package.json | 15 ++++++++------- .../04-component-unmount/package.json | 15 ++++++++------- .../05-component-update-render/package.json | 15 ++++++++------- 12 files changed, 84 insertions(+), 64 deletions(-) diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/package.json b/04-frameworks/01-react/02-base/01-vite-boiler/package.json index 964563240..dfcbe9038 100644 --- a/04-frameworks/01-react/02-base/01-vite-boiler/package.json +++ b/04-frameworks/01-react/02-base/01-vite-boiler/package.json @@ -9,7 +9,6 @@ "preview": "vite preview" }, "devDependencies": { - "tslib": "^2.8.1", "typescript": "^5.9.2", "vite": "^7.1.3", "vite-plugin-checker": "^0.10.2" diff --git a/04-frameworks/01-react/02-base/02-vite-react/package.json b/04-frameworks/01-react/02-base/02-vite-react/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/package.json +++ b/04-frameworks/01-react/02-base/02-vite-react/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme.md b/04-frameworks/01-react/02-base/02-vite-react/readme.md index ed3f4cff2..a8b4b8812 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme.md @@ -21,6 +21,12 @@ npm install npm install react react-dom --save ``` +- No install types for `react` y `react-dom` ad dev dependencies: + +```bash +npm install @types/react @types/react-dom -D +``` + - Now open `tsconfig.json` file and set following compiler option to support `jsx` notation in our TypeScript files: _tsconfig.json_ diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md index d575f2b85..a862f526e 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md @@ -20,6 +20,12 @@ npm install npm install react react-dom --save ``` +- A continuación instalamos los tipos de las librerías `react` y `react-dom` como dependencias de desarrollo: + +```bash +npm install @types/react @types/react-dom -D +``` + - Para hacer que TS entienda la notación `jsx` añadimos lo siguiente en el fichero `tsconfig.json`: _tsconfig.json_ diff --git a/04-frameworks/01-react/02-base/03-list-users/package.json b/04-frameworks/01-react/02-base/03-list-users/package.json index b76d9beec..9f55e25d6 100644 --- a/04-frameworks/01-react/02-base/03-list-users/package.json +++ b/04-frameworks/01-react/02-base/03-list-users/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.12", + "@types/react-dom": "^19.1.9", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/02-base/04-list-refactor/package.json b/04-frameworks/01-react/02-base/04-list-refactor/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/02-base/04-list-refactor/package.json +++ b/04-frameworks/01-react/02-base/04-list-refactor/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/package.json b/04-frameworks/01-react/03-react-hooks/01-use-state/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/package.json +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json b/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json b/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json b/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json b/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json index b76d9beec..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/package.json @@ -9,14 +9,15 @@ "preview": "vite preview" }, "devDependencies": { - "@vitejs/plugin-react": "^5.0.1", - "tslib": "^2.8.1", - "typescript": "^5.9.2", - "vite": "^7.1.3", - "vite-plugin-checker": "^0.10.2" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } From 09c9ba3661505b043d711cf02d3ae49519a8aa0a Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 17:31:11 +0200 Subject: [PATCH 18/31] refactor react 19 - vite - ajax fields exercise --- .../06-ajax-field-change/{src => }/index.html | 9 ++-- .../06-ajax-field-change/package.json | 24 +++++++++ .../06-ajax-field-change/tsconfig.json | 19 +++++++ .../06-ajax-field-change/vite.config.ts | 7 +++ .../03-react-hooks/07-custom-hook/.babelrc | 7 --- .../07-custom-hook/{src => }/index.html | 9 ++-- .../07-custom-hook/package.json | 48 ++++++----------- .../07-custom-hook/tsconfig.json | 25 ++++----- .../07-custom-hook/vite.config.ts | 7 +++ .../07-custom-hook/webpack.config.js | 54 ------------------- 10 files changed, 96 insertions(+), 113 deletions(-) rename 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json create mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json create mode 100644 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/.babelrc rename 04-frameworks/01-react/03-react-hooks/07-custom-hook/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/src/index.html b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/src/index.html rename to 04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json new file mode 100644 index 000000000..cb10a2306 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/package.json @@ -0,0 +1,24 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0", + "use-debounce": "^10.0.5" + } +} diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/vite.config.ts b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/.babelrc b/04-frameworks/01-react/03-react-hooks/07-custom-hook/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.html b/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.html rename to 04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/package.json b/04-frameworks/01-react/03-react-hooks/07-custom-hook/package.json index d434b896c..cb10a2306 100644 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/package.json +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/package.json @@ -1,40 +1,24 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0", + "use-debounce": "^10.0.5" } } diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/tsconfig.json b/04-frameworks/01-react/03-react-hooks/07-custom-hook/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/vite.config.ts b/04-frameworks/01-react/03-react-hooks/07-custom-hook/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/webpack.config.js b/04-frameworks/01-react/03-react-hooks/07-custom-hook/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 3ade6fc6ad2bebd7ea7d55b160a2b3d3291f325b Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 17:31:35 +0200 Subject: [PATCH 19/31] new example of use hook - react 19 --- .../01-react/03-react-hooks/18-use/Readme.md | 123 ++++++++++++ .../03-react-hooks/18-use/Readme_es.md | 184 ++++++++++++++++++ .../01-react/03-react-hooks/18-use/index.html | 13 ++ .../03-react-hooks/18-use/package.json | 24 +++ .../03-react-hooks/18-use/src/app.tsx | 35 ++++ .../03-react-hooks/18-use/src/demo.tsx | 20 ++ .../03-react-hooks/18-use/src/index.tsx | 8 + .../03-react-hooks/18-use/src/styles.css | 3 + .../03-react-hooks/18-use/tsconfig.json | 19 ++ .../03-react-hooks/18-use/vite.config.ts | 7 + 10 files changed, 436 insertions(+) create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/Readme.md create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/package.json create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/src/styles.css create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts diff --git a/04-frameworks/01-react/03-react-hooks/18-use/Readme.md b/04-frameworks/01-react/03-react-hooks/18-use/Readme.md new file mode 100644 index 000000000..b7789b8e5 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/Readme.md @@ -0,0 +1,123 @@ +# 06 Ajax field change + +## Resume + +This example takes as a starting point the example \ \_05-component-update-render. + +Let's simulate a real scenario, we have a search result list(we read this from a server source), and each time that we enter a change to a filtering input we want to send a request to the server to get the new filtered list and display it. + +As a bonus, we will check how to use Debounce (wait a little until the user stops typing to send the request, saving so unnecessary calls). + +# Steps + +- First we copy the previous example, and do a _npm install_. + +```bash +npm install +``` + +- Let's open the _demo.js_, and let's add an entry in the state that stores the current search filter, and another state in which we + are going to store a list of users. + +_./src/demo.tsx_ + +```tsx +import React from "react"; + +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); + const [userCollection, setUserCollection] = React.useState([]); + + return ( +
+ setFilter(e.target.value)} /> +
    + {userCollection.map((user, index) => ( +
  • {user.name}
  • + ))} +
+
+ ); +}; +``` + +- Now we want to fire an _ajax request_ every time the user types on the filter input. + +_./src/demo.tsx_ + +```diff +export const MyComponent = () => { + const [filter, setFilter] = React.useState(''); + const [userCollection, setUserCollection] = React.useState([]); + ++ // Load full list when the component gets mounted and filter gets updated ++ React.useEffect(() => { ++ fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) ++ .then(response => response.json()) ++ .then(json => setUserCollection(json)); ++ }, [filter]); + + return ( +``` + +**BE CAREFUL!!! Typicode** since we are hitting a free rest api it maybe down or asleep, maybe you will have to give some tries :). + +You can try as with other apis as well (you will need to take a look at the documention, some of them return slightly different +response structures). + +https://rickandmortyapi.com/ + +https://swapi.dev/documentation#auth + +```tsx +React.useEffect(() => { + fetch(`https://swapi.dev/api/people?search=${filter}`) + .then((response) => response.json()) + .then((json) => setUserCollection(json.results)); +}, [filter]); +``` + +- If we execute this code we can see that the filtering option works. + +```bash +npm start +``` + +## BONUS + +This is fine, but it isn't optimal, we usually want to trigger the search just when the user has stopped typing to avoid making unnecessary calls. + +We can download a library that implements a custom hook that just implements that behavior: https://github.com/xnimorz/use-debounce + +Using this is a piece of cake: + +```bash +npm install use-debounce --save +``` + +```diff ++ import { useDebounce } from 'use-debounce'; + +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); ++ const [debouncedFilter] = useDebounce(filter, 500); + const [userCollection, setUserCollection] = React.useState([]); + + // Load full list when the component gets mounted and filter gets updated + React.useEffect(() => { + fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) + .then((response) => response.json()) + .then((json) => setUserCollection(json)); +- }, [filter]); ++ }, [debouncedFilter]); +``` + +# About Basefactor + Lemoncode + +We are an innovating team of Javascript experts, passionate about turning your ideas into robust products. + +[Basefactor, consultancy by Lemoncode](http://www.basefactor.com) provides consultancy and coaching services. + +[Lemoncode](http://lemoncode.net/services/en/#en-home) provides training services. + +For the LATAM/Spanish audience we are running an Online Front End Master degree, more info: http://lemoncode.net/master-frontend diff --git a/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md b/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md new file mode 100644 index 000000000..6e0d253f3 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md @@ -0,0 +1,184 @@ +# 06 AJAX Field Change + +## Resumen + +Este ejemplo toma como punto de partida el ejemplo \_05-component-update-render. + +Pasamos a ver un ejemplo práctico, tenemos un listado de resultado de busqueda +(esto viene de un servidor), y queremos que cada vez que introduzcamos un +cambio en un input de filtrado, envíe una petición a servidor para obtener +la nueva lista filtrada y mostrarla. + +Como postre veremos como utilizar Debounce (es decir esperar un poquito a +que el usuario termine de teclear para enviar la petición, ahorrando +así llamadas innecesarias). + +## Paso a Paso + +- Primero copiamos el ejemplo anterior, y hacemos un _npm install_. + +```bash +npm install +``` + +- Vamos abrir el fichero _demo.js_ y vamos añadir una entrada en el + estado que almacene el filtro actual de busqueda, y otra en la que almacene + una lista de usuarios. + +_./src/demo.tsx_ + +```tsx +import React from "react"; + +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); + const [userCollection, setUserCollection] = React.useState([]); + + return ( +
+ setFilter(e.target.value)} /> +
    + {userCollection.map((user, index) => ( +
  • {user.name}
  • + ))} +
+
+ ); +}; +``` + +- Ahora vamos a acceder a un rest api json, _typicode_ nos da alguna gratuita, + esta por ejemplo: _https://jsonplaceholder.typicode.com/users_ además permite + aplicar filtrados, la ponemos en el useEffecy y le añadimos como filtro que + se ejecute cada vez que se cambie el filtro de busqueda: + +```diff +export const MyComponent = () => { + const [filter, setFilter] = React.useState(''); + const [userCollection, setUserCollection] = React.useState([]); + ++ // Load full list when the component gets mounted and filter gets updated ++ React.useEffect(() => { ++ fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) ++ .then(response => response.json()) ++ .then(json => setUserCollection(json)); ++ }, [filter]); + + return ( +``` + +**OJO !!! Typicode** corre en un heroku gratuito que se duerme cada X tiempo :) +Vamos a probar con otras API. + +Ojo, que esto impactara en el codigo, tenemos que meter algún cambio y +ver que devuelven estas api, esto lo haremos como ejercicio. + +**EJERCICIO RICK AND MORTY API** + +https://rickandmortyapi.com/ + +https://swapi.dev/documentation#auth + +```tsx +React.useEffect(() => { + fetch(`https://swapi.dev/api/people?search=${filter}`) + .then((response) => response.json()) + .then((json) => setUserCollection(json.results)); +}, [filter]); +``` + +- Si ejecutamos este código podemos ver que la opcíon de filtrado funciona. + +```bash +npm start +``` + +## BONUS + +### A. useDebounce + +Esto está bien, pero no es optimo, normalmente queremos disparar la busqueda +justo cuando el usuario ha dejado de teclear para evitar hacer llamadas +innecesarias. + +Nos podemos bajar una librería que implement un custom hook que hace +justo eso: https://github.com/xnimorz/use-debounce + +Lo único que tendríamos que hacer: + +```bash +npm install use-debounce --save +``` + +```diff ++ import { useDebounce } from 'use-debounce'; + +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); ++ const [debouncedFilter] = useDebounce(filter, 500); + const [userCollection, setUserCollection] = React.useState([]); + + // Load full list when the component gets mounted and filter gets updated + React.useEffect(() => { +- fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) ++ fetch(`https://jsonplaceholder.typicode.com/users?name_like=${debouncedFilter}`) + + .then((response) => response.json()) + .then((json) => setUserCollection(json)); +- }, [filter]); ++ }, [debouncedFilter]); +``` + +### B. useDeferredValue + +En React 18 han metido un nuevo hook interesante y es poder +jugar actualizando a dos tiempos: + +- En el debounce nosotros artificialmente esperamos a + que el usuario deje de teclear para actualizar. + +- En useDeffered lo que hacemos es actualizar un valor con + un retraso. + +Esto nos puede servir cuando tenemos operaciones que pueden +tardar más (por ejemplo pedir listad de fotos a una api , versus +rellenar el texto de busqueda que queremos). + +Vamos a cambiar el uso de useDebounce por useDeferredValue: + +```diff +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); + const [userCollection, setUserCollection] = React.useState([]); +- const [debouncedFilter] = useDebounce(filter, 500); ++ const deferredFilter = React.useDeferredValue(filter, {timeoutMs:500 }); +``` + +```diff + React.useEffect(() => { + fetch( +- `https://jsonplaceholder.typicode.com/users?name_like=${debouncedFilter}` ++ `https://jsonplaceholder.typicode.com/users?name_like=${deferredFilter}` + + ) + .then((response) => response.json()) + .then((json) => setUserCollection(json)); +- }, [debouncedFilter]); ++ }, [deferredFilter]); + +``` + +Aquí no vemos mucho efecto, esto es más para da prioridades de renderizado. + +# ¿Te apuntas a nuestro máster? + +Si te ha gustado este ejemplo y tienes ganas de aprender Front End +guiado por un grupo de profesionales ¿Por qué no te apuntas a +nuestro [Máster Front End Online Lemoncode](https://lemoncode.net/master-frontend#inicio-banner)? Tenemos tanto edición de convocatoria +con clases en vivo, como edición continua con mentorización, para +que puedas ir a tu ritmo y aprender mucho. + +Si lo que te gusta es el mundo del _backend_ también puedes apuntante a nuestro [Bootcamp backend Online Lemoncode](https://lemoncode.net/bootcamp-backend#bootcamp-backend/inicio) + +Y si tienes ganas de meterte una zambullida en el mundo _devops_ +apuntate nuestro [Bootcamp devops online Lemoncode](https://lemoncode.net/bootcamp-devops#bootcamp-devops/inicio) diff --git a/04-frameworks/01-react/03-react-hooks/18-use/index.html b/04-frameworks/01-react/03-react-hooks/18-use/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/03-react-hooks/18-use/package.json b/04-frameworks/01-react/03-react-hooks/18-use/package.json new file mode 100644 index 000000000..cb10a2306 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/package.json @@ -0,0 +1,24 @@ +{ + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0", + "use-debounce": "^10.0.5" + } +} diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx new file mode 100644 index 000000000..e2f5be914 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx @@ -0,0 +1,35 @@ +import React, { Suspense } from "react"; +import { useDebounce } from "use-debounce"; +import { MyComponent } from "./demo"; + +export interface User { + id: number; + name: string; +} + +export const fetchUsers = async (filter): Promise => { + const res = await fetch( + `https://jsonplaceholder.typicode.com/users?name_like=${filter}` + ); + return res.json(); +}; + +export const App = () => { + const [filter, setFilter] = React.useState(""); + const [debouncedFilter] = useDebounce(filter, 1500); + + const usersPromise = React.useMemo( + () => fetchUsers(debouncedFilter), + [debouncedFilter] + ); + + return ( + <> + setFilter(e.target.value)} /> + Debounced filter: {debouncedFilter} + Loading...
}> + + + + ); +}; diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx new file mode 100644 index 000000000..253da41ec --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx @@ -0,0 +1,20 @@ +import React, { use } from "react"; +import { User } from "./app"; + +interface MyComponentProps { + usersPromise: Promise; +} + +export const MyComponent: React.FC = ({ usersPromise }) => { + const users = use(usersPromise); + + return ( +
+
    + {users?.map((user, index) => ( +
  • {user.name}
  • + ))} +
+
+ ); +}; diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx new file mode 100644 index 000000000..7e439b87e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; + +const container = document.getElementById("root"); +const root = createRoot(container); + +root.render(); diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/styles.css b/04-frameworks/01-react/03-react-hooks/18-use/src/styles.css new file mode 100644 index 000000000..74dc08fbb --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/styles.css @@ -0,0 +1,3 @@ +.my-text { + color: blue; +} diff --git a/04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json b/04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json new file mode 100644 index 000000000..a057cea1d --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true + }, + "include": ["src"] +} diff --git a/04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts b/04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); From 4802b16800e043ee929dd31b28f64ab5ceed1989 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 20:10:43 +0200 Subject: [PATCH 20/31] example of use hook - review --- .../03-react-hooks/18-use/Readme_es.md | 300 ++++++++++++------ .../03-react-hooks/18-use/src/app.tsx | 35 +- .../03-react-hooks/18-use/src/demo.tsx | 10 +- .../03-react-hooks/18-use/src/parent.tsx | 34 ++ 4 files changed, 239 insertions(+), 140 deletions(-) create mode 100644 04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx diff --git a/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md b/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md index 6e0d253f3..2ba616fd0 100644 --- a/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md @@ -1,29 +1,10 @@ -# 06 AJAX Field Change +# 06 Use hook -## Resumen +Vamos a ver el nuevo hook _use_, introducido en la versión 19 de react. En este ejemplo vamos a usar el hook para consumir datos que recibimos de manera asíncrona, haciendo una petición al servidor. -Este ejemplo toma como punto de partida el ejemplo \_05-component-update-render. +## Punto de Partida -Pasamos a ver un ejemplo práctico, tenemos un listado de resultado de busqueda -(esto viene de un servidor), y queremos que cada vez que introduzcamos un -cambio en un input de filtrado, envíe una petición a servidor para obtener -la nueva lista filtrada y mostrarla. - -Como postre veremos como utilizar Debounce (es decir esperar un poquito a -que el usuario termine de teclear para enviar la petición, ahorrando -así llamadas innecesarias). - -## Paso a Paso - -- Primero copiamos el ejemplo anterior, y hacemos un _npm install_. - -```bash -npm install -``` - -- Vamos abrir el fichero _demo.js_ y vamos añadir una entrada en el - estado que almacene el filtro actual de busqueda, y otra en la que almacene - una lista de usuarios. +Este ejemplo parte del ejercicio \_06-ajax-field-change. Si no tienes el código a mano te lo dejamos por aquí. _./src/demo.tsx_ @@ -34,6 +15,12 @@ export const MyComponent = () => { const [filter, setFilter] = React.useState(""); const [userCollection, setUserCollection] = React.useState([]); + React.useEffect(() => { + fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) + .then((response) => response.json()) + .then((json) => setUserCollection(json)); + }, [filter]); + return (
setFilter(e.target.value)} /> @@ -47,128 +34,235 @@ export const MyComponent = () => { }; ``` -- Ahora vamos a acceder a un rest api json, _typicode_ nos da alguna gratuita, - esta por ejemplo: _https://jsonplaceholder.typicode.com/users_ además permite - aplicar filtrados, la ponemos en el useEffecy y le añadimos como filtro que - se ejecute cada vez que se cambie el filtro de busqueda: +_./src/app.tsx_ + +```tsx +import React from "react"; +import { MyComponent } from "./demo"; + +export const App = () => { + return ; +}; +``` + +## Paso a Paso + +Primero hacemos un _npm install_. + +```bash +npm install +``` + +Lo primero que necesitamos es una llamada asíncrona. Vamos a crearnos por el momento una llamada que no ataque a ningún servidor, sino que simplemente devuelva usuarios mockeados. Introducimos además un log para ver cuantas veces se ejecuta la función. + +En _./src/demo.tsx_ ```diff +import React from "react"; + ++ const fetchMockedUsers = async () => { ++ console.log("executed"); ++ const res = await Promise.resolve([{ name: "Test user", id: 1 }]); ++ return res; ++ }; + export const MyComponent = () => { - const [filter, setFilter] = React.useState(''); - const [userCollection, setUserCollection] = React.useState([]); +``` + +El hook use se va a encargar de gestionar la llamada y de devolvernos el estado, por lo que podemos reemplazar el useState y el useEffect. + +En _./src/demo.tsx_ + +```diff +- import React from "react"; ++ import React, { use } from "react"; + + +export const MyComponent = () => { + const [filter, setFilter] = React.useState(""); ++ const userCollection = use(fetchMockedUsers()) +- const [userCollection, setUserCollection] = React.useState([]); -+ // Load full list when the component gets mounted and filter gets updated -+ React.useEffect(() => { -+ fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) -+ .then(response => response.json()) -+ .then(json => setUserCollection(json)); -+ }, [filter]); +- React.useEffect(() => { +- fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) +- .then((response) => response.json()) +- .then((json) => setUserCollection(json)); +- }, [filter]); return ( ``` -**OJO !!! Typicode** corre en un heroku gratuito que se duerme cada X tiempo :) -Vamos a probar con otras API. +Si levantamos el proyecto, abrimos las _devTools_ y vemos los logs del browser, nos damos cuenta de que hemos entrado en un bucle infinito (el log debe aparecer muchas veces). Esto se debe a como funciona el hook _use_ por dentro y a que nos hemos saltado una regla fundamental establecida por la documentación de React: al hook _use_ hay que pasarle una referencia estable. +Esto se diferencia a lo que hemos hecho dentro de nuestro componente, donde dentro de cada ejecución _fetchMockedUsers()_ crea una nueva referencia en cada re-ejecución, por lo que el componente se va a re-ejecutar infinitas veces. -Ojo, que esto impactara en el codigo, tenemos que meter algún cambio y -ver que devuelven estas api, esto lo haremos como ejercicio. +Para poder adaptarnos a las condiciones de uso de _use_ esa referencia debe ser estable, por lo que le deberá llegar a nuestro componente como _prop_. De esta manera esa _prop_ no se calculará en cada ejecución. -**EJERCICIO RICK AND MORTY API** +Así, nos creamos un componente padre _MyParentComponent_ que wrapee a _MyComponent_. -https://rickandmortyapi.com/ +- Movemos _fetchMockedUsers_ a este fichero +- Creamos User interface. +- Introducimos _Suspense_, requerido para poder usar _use_. Este componente nos permitirá usar un fallback mientras la llamada está pendiente de resolverse. -https://swapi.dev/documentation#auth +_./src/parent.tsx_ ```tsx -React.useEffect(() => { - fetch(`https://swapi.dev/api/people?search=${filter}`) - .then((response) => response.json()) - .then((json) => setUserCollection(json.results)); -}, [filter]); -``` - -- Si ejecutamos este código podemos ver que la opcíon de filtrado funciona. +import React, { Suspense } from "react"; +import { MyComponent } from "./demo"; + +export interface User { + id: number; + name: string; +} + +const fetchMockedUsers = async () => { + console.log("executed"); + const res = await Promise.resolve([{ name: "Test user", id: 1 }]); + return res; +}; -```bash -npm start +export const MyParentComponent = () => { + const mockedUsersPromise = fetchMockedUsers(); + return ( + <> + Loading}> + + + + ); +}; ``` -## BONUS +Actualizamos en _./src/demo.tsx_: + +- Tipamos _MyComponent_ correctamente. +- _MyComponent_ recibe la nueva prop. +- Eliminamos _fetchMockedUsers_. -### A. useDebounce +```diff +import React, { use } from "react"; ++ import { User } from './parent'; -Esto está bien, pero no es optimo, normalmente queremos disparar la busqueda -justo cuando el usuario ha dejado de teclear para evitar hacer llamadas -innecesarias. +- export const fetchMockedUsers = async () => { +- console.log("executed"); +- const res = await Promise.resolve([{ name: "Test user", id: 1 }]); +- return res; +- }; -Nos podemos bajar una librería que implement un custom hook que hace -justo eso: https://github.com/xnimorz/use-debounce ++ interface MyComponentProps { ++ userPromise: Promise ++ } -Lo único que tendríamos que hacer: +- export const MyComponent = () => { ++ export const MyComponent: React.FC = ({ userPromise }) => { + const [filter, setFilter] = React.useState(""); +- const userCollection = use(fetchMockedUsers()); ++ const userCollection = use(userPromise); -```bash -npm install use-debounce --save + return ( ``` +Reemplazamos en _./src/app.tsx_ + ```diff -+ import { useDebounce } from 'use-debounce'; +import React from "react"; +- import { MyComponent } from "./demo"; ++ import { MyParentComponent } from "./parent"; -export const MyComponent = () => { - const [filter, setFilter] = React.useState(""); -+ const [debouncedFilter] = useDebounce(filter, 500); - const [userCollection, setUserCollection] = React.useState([]); +export const App = () => { +- return ; ++ return ; +}; +``` - // Load full list when the component gets mounted and filter gets updated - React.useEffect(() => { -- fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) -+ fetch(`https://jsonplaceholder.typicode.com/users?name_like=${debouncedFilter}`) +Comprobamos que la aplicación funciona. - .then((response) => response.json()) - .then((json) => setUserCollection(json)); -- }, [filter]); -+ }, [debouncedFilter]); +Ahora que ya sabemos que no estamos incurriendo en bucles infinitos es seguro sustituir la función mock por la llamada real. Además, al estar interpolando dentro de la llamada _filter_, nos tenemos que traer el estado y el input que lo setea. + +_./src/parent.tsx_ + +```diff +export interface User { + id: number; + name: string; +} + +- const fetchMockedUsers = async () => { +- console.log("executed"); +- const res = await Promise.resolve([{ name: "Test user", id: 1 }]); +- return res; +- }; + ++ const fetchUsers = async (filter): Promise => { ++ const res = await fetch( ++ `https://jsonplaceholder.typicode.com/users?name_like=${filter}` ++ ); ++ return res.json(); ++ }; + +export const MyParentComponent = () => { ++ const [filter, setFilter] = React.useState(""); +- const mockedUsersPromise = fetchMockedUsers(); ++ const usersPromise = fetchUsers(filter); + + return ( + <> ++ setFilter(e.target.value)} /> + Loading}> +- ++ + + + ); +}; ``` -### B. useDeferredValue +Eliminamos de _MyComponent_, el estado _filter_ y el input que lo setea: -En React 18 han metido un nuevo hook interesante y es poder -jugar actualizando a dos tiempos: +_./src/demo.tsx_ -- En el debounce nosotros artificialmente esperamos a - que el usuario deje de teclear para actualizar. +```diff +export const MyComponent: React.FC = ({ userPromise }) => { +- const [filter, setFilter] = React.useState(""); + const userCollection = use(userPromise); -- En useDeffered lo que hacemos es actualizar un valor con - un retraso. + return ( +
+- setFilter(e.target.value)} /> +
    +``` -Esto nos puede servir cuando tenemos operaciones que pueden -tardar más (por ejemplo pedir listad de fotos a una api , versus -rellenar el texto de busqueda que queremos). +Y si quisiéramos implementar el useDebounce? -Vamos a cambiar el uso de useDebounce por useDeferredValue: +- Instalamos la librería _use-debounce_ como dependencia -```diff -export const MyComponent = () => { - const [filter, setFilter] = React.useState(""); - const [userCollection, setUserCollection] = React.useState([]); -- const [debouncedFilter] = useDebounce(filter, 500); -+ const deferredFilter = React.useDeferredValue(filter, {timeoutMs:500 }); +```bash +npm i use-debounce ``` +En _./src/parent.tsx_: + ```diff - React.useEffect(() => { - fetch( -- `https://jsonplaceholder.typicode.com/users?name_like=${debouncedFilter}` -+ `https://jsonplaceholder.typicode.com/users?name_like=${deferredFilter}` +import React, { Suspense } from "react"; ++ import { useDebounce } from "use-debounce"; - ) - .then((response) => response.json()) - .then((json) => setUserCollection(json)); -- }, [debouncedFilter]); -+ }, [deferredFilter]); +(...) -``` +export const MyParentComponent = () => { + const [filter, setFilter] = React.useState(""); ++ const [debouncedFilter] = useDebounce(filter, 1500); +- const usersPromise = fetchUsers(filter); + ++ const usersPromise = React.useMemo( ++ () => fetchUsers(debouncedFilter), ++ [debouncedFilter] ++ ); -Aquí no vemos mucho efecto, esto es más para da prioridades de renderizado. + return ( + <> ++
    Debounced filter: {debouncedFilter}
    + setFilter(e.target.value)} /> + Loading}> +``` # ¿Te apuntas a nuestro máster? diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx index e2f5be914..69c1d3337 100644 --- a/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx @@ -1,35 +1,6 @@ -import React, { Suspense } from "react"; -import { useDebounce } from "use-debounce"; -import { MyComponent } from "./demo"; - -export interface User { - id: number; - name: string; -} - -export const fetchUsers = async (filter): Promise => { - const res = await fetch( - `https://jsonplaceholder.typicode.com/users?name_like=${filter}` - ); - return res.json(); -}; +import React from "react"; +import { MyParentComponent } from "./parent"; export const App = () => { - const [filter, setFilter] = React.useState(""); - const [debouncedFilter] = useDebounce(filter, 1500); - - const usersPromise = React.useMemo( - () => fetchUsers(debouncedFilter), - [debouncedFilter] - ); - - return ( - <> - setFilter(e.target.value)} /> - Debounced filter: {debouncedFilter} - Loading...
}> - - - - ); + return ; }; diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx index 253da41ec..de7b9d074 100644 --- a/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx @@ -1,17 +1,17 @@ import React, { use } from "react"; -import { User } from "./app"; +import { User } from "./parent"; interface MyComponentProps { - usersPromise: Promise; + userPromise: Promise; } -export const MyComponent: React.FC = ({ usersPromise }) => { - const users = use(usersPromise); +export const MyComponent: React.FC = ({ userPromise }) => { + const userCollection = use(userPromise); return (
    - {users?.map((user, index) => ( + {userCollection.map((user, index) => (
  • {user.name}
  • ))}
diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx b/04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx new file mode 100644 index 000000000..24c7bb748 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx @@ -0,0 +1,34 @@ +import React, { Suspense } from "react"; +import { useDebounce } from "use-debounce"; +import { MyComponent } from "./demo"; + +export interface User { + id: number; + name: string; +} + +const fetchUsers = async (filter): Promise => { + const res = await fetch( + `https://jsonplaceholder.typicode.com/users?name_like=${filter}` + ); + return res.json(); +}; + +export const MyParentComponent = () => { + const [filter, setFilter] = React.useState(""); + const [debouncedFilter] = useDebounce(filter, 1500); + + const usersPromise = React.useMemo( + () => fetchUsers(debouncedFilter), + [debouncedFilter] + ); + + return ( + <> + setFilter(e.target.value)} /> + Loading}> + + + + ); +}; From a8f047bf6dbe7f03bff5b007d9ad19c28b21597d Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 20:12:08 +0200 Subject: [PATCH 21/31] folder rename --- .../01-react/03-react-hooks/{18-use => 18-use-promise}/Readme.md | 0 .../03-react-hooks/{18-use => 18-use-promise}/Readme_es.md | 0 .../01-react/03-react-hooks/{18-use => 18-use-promise}/index.html | 0 .../03-react-hooks/{18-use => 18-use-promise}/package.json | 0 .../03-react-hooks/{18-use => 18-use-promise}/src/app.tsx | 0 .../03-react-hooks/{18-use => 18-use-promise}/src/demo.tsx | 0 .../03-react-hooks/{18-use => 18-use-promise}/src/index.tsx | 0 .../03-react-hooks/{18-use => 18-use-promise}/src/parent.tsx | 0 .../03-react-hooks/{18-use => 18-use-promise}/src/styles.css | 0 .../03-react-hooks/{18-use => 18-use-promise}/tsconfig.json | 0 .../03-react-hooks/{18-use => 18-use-promise}/vite.config.ts | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/Readme.md (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/Readme_es.md (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/index.html (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/package.json (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/src/app.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/src/demo.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/src/index.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/src/parent.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/src/styles.css (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/tsconfig.json (100%) rename 04-frameworks/01-react/03-react-hooks/{18-use => 18-use-promise}/vite.config.ts (100%) diff --git a/04-frameworks/01-react/03-react-hooks/18-use/Readme.md b/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/Readme.md rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md diff --git a/04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md b/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme_es.md similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/Readme_es.md rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/Readme_es.md diff --git a/04-frameworks/01-react/03-react-hooks/18-use/index.html b/04-frameworks/01-react/03-react-hooks/18-use-promise/index.html similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/index.html rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/index.html diff --git a/04-frameworks/01-react/03-react-hooks/18-use/package.json b/04-frameworks/01-react/03-react-hooks/18-use-promise/package.json similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/package.json rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/package.json diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx b/04-frameworks/01-react/03-react-hooks/18-use-promise/src/app.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/src/app.tsx rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/src/app.tsx diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/18-use-promise/src/demo.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/src/demo.tsx rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/src/demo.tsx diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx b/04-frameworks/01-react/03-react-hooks/18-use-promise/src/index.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/src/index.tsx rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/src/index.tsx diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx b/04-frameworks/01-react/03-react-hooks/18-use-promise/src/parent.tsx similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/src/parent.tsx rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/src/parent.tsx diff --git a/04-frameworks/01-react/03-react-hooks/18-use/src/styles.css b/04-frameworks/01-react/03-react-hooks/18-use-promise/src/styles.css similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/src/styles.css rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/src/styles.css diff --git a/04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json b/04-frameworks/01-react/03-react-hooks/18-use-promise/tsconfig.json similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/tsconfig.json rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/tsconfig.json diff --git a/04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts b/04-frameworks/01-react/03-react-hooks/18-use-promise/vite.config.ts similarity index 100% rename from 04-frameworks/01-react/03-react-hooks/18-use/vite.config.ts rename to 04-frameworks/01-react/03-react-hooks/18-use-promise/vite.config.ts From a5dc3f232c843eaa273c1391435ca9e68bb6e9e6 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 21:27:46 +0200 Subject: [PATCH 22/31] refactor react 19 - vite - pure and memos --- .../03-react-hooks/08-pure-component/.babelrc | 7 --- .../src => 08-pure-component}/index.html | 9 ++-- .../08-pure-component/package.json | 47 ++++++---------- .../08-pure-component/tsconfig.json | 25 ++++----- .../08-pure-component/vite.config.ts | 7 +++ .../08-pure-component/webpack.config.js | 54 ------------------- .../09-pure-component-callback/.babelrc | 7 --- .../index.html | 9 ++-- .../09-pure-component-callback/package.json | 47 ++++++---------- .../09-pure-component-callback/tsconfig.json | 25 ++++----- .../09-pure-component-callback/vite.config.ts | 7 +++ .../webpack.config.js | 54 ------------------- .../10-use-reducer/{src => }/index.html | 9 ++-- .../10-use-reducer/package.json | 47 ++++++---------- .../10-use-reducer/tsconfig.json | 25 ++++----- .../10-use-reducer/vite.config.ts | 7 +++ .../10-use-reducer/webpack.config.js | 54 ------------------- 17 files changed, 120 insertions(+), 320 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/08-pure-component/.babelrc rename 04-frameworks/01-react/03-react-hooks/{09-pure-component-callback/src => 08-pure-component}/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/08-pure-component/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/08-pure-component/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/09-pure-component-callback/.babelrc rename 04-frameworks/01-react/03-react-hooks/{08-pure-component/src => 09-pure-component-callback}/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/09-pure-component-callback/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/09-pure-component-callback/webpack.config.js rename 04-frameworks/01-react/03-react-hooks/10-use-reducer/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/10-use-reducer/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/10-use-reducer/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/.babelrc b/04-frameworks/01-react/03-react-hooks/08-pure-component/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/src/index.html b/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/09-pure-component-callback/src/index.html rename to 04-frameworks/01-react/03-react-hooks/08-pure-component/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/package.json b/04-frameworks/01-react/03-react-hooks/08-pure-component/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/package.json +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/tsconfig.json b/04-frameworks/01-react/03-react-hooks/08-pure-component/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/vite.config.ts b/04-frameworks/01-react/03-react-hooks/08-pure-component/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/webpack.config.js b/04-frameworks/01-react/03-react-hooks/08-pure-component/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/.babelrc b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/src/index.html b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/08-pure-component/src/index.html rename to 04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/package.json b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/package.json +++ b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/tsconfig.json b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/vite.config.ts b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/webpack.config.js b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/src/index.html b/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/10-use-reducer/src/index.html rename to 04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/package.json b/04-frameworks/01-react/03-react-hooks/10-use-reducer/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/package.json +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/tsconfig.json b/04-frameworks/01-react/03-react-hooks/10-use-reducer/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/vite.config.ts b/04-frameworks/01-react/03-react-hooks/10-use-reducer/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/webpack.config.js b/04-frameworks/01-react/03-react-hooks/10-use-reducer/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 5f5ec077eb3dd4302c9ec0ddd674af12a48fedcf Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 21:32:03 +0200 Subject: [PATCH 23/31] refactor react 19 - vite - README - contexts --- .../03-react-hooks/10-use-reducer/.babelrc | 7 --- .../03-react-hooks/11-use-context/.babelrc | 7 --- .../03-react-hooks/11-use-context/Readme.md | 38 ++++++++++--- .../11-use-context/Readme_es.md | 33 ++++++++++-- .../11-use-context/{src => }/index.html | 9 ++-- .../11-use-context/package.json | 47 ++++++---------- .../11-use-context/src/demo.tsx | 4 +- .../11-use-context/tsconfig.json | 25 ++++----- .../11-use-context/vite.config.ts | 7 +++ .../11-use-context/webpack.config.js | 54 ------------------- 10 files changed, 101 insertions(+), 130 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/10-use-reducer/.babelrc delete mode 100644 04-frameworks/01-react/03-react-hooks/11-use-context/.babelrc rename 04-frameworks/01-react/03-react-hooks/11-use-context/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/11-use-context/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/11-use-context/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/.babelrc b/04-frameworks/01-react/03-react-hooks/10-use-reducer/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/.babelrc b/04-frameworks/01-react/03-react-hooks/11-use-context/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md index d14673dd6..79b9d4243 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md @@ -36,22 +36,22 @@ userGlobalDAta.login = "john"; This approach that we could first try to defend (it is flat ES6, so React account only takes care of the UI...), it brings us several problems: -- What if the value of _userGlobalData.login_ changes and I have multiple parts of the application they are using it? How do I notify you of the change? Would have to play pulling and collecting global events to go repainting. +- What if the value of _userGlobalData.login_ changes and I have multiple parts of the application they are using it? How do I notify you of the change? Would have to play pulling and collecting global events to go repainting. - And now to finish, if I want to use Server Side Rendering (that is, pregenerate the pages on the server to serve HTML, this is good for example for have a good SEO), we would have a big problem ... communicating vessels, all the requests would share the same static variables. React incorporates a very powerful mechanism, it is called ** Context ** - - The ** Context ** allows me to share data between components without going through the props. - The Context lives within a React component, with which it is integrated into the React one-way flow, that is, any change you make to it makes updates to be triggered automatically. - I can place the Context at the level I want in the component tree, that is, I can make that data available at the full application level or for example a window containing several tabs. - And to all this we have to add that React incorporates a hook called -_useContext_ which makes using it very easy. +_use_ which makes using it very easy. + +**In previous versions to react 19, use _usecontext_ to consume contexts** Let's see how this works. @@ -99,13 +99,36 @@ const MyContext = React.createContext({ + const [username, setUsername] = React.useState("John Doe"); + + return ( -+ ++ + {props.children} -+ ++ + ); + }; ``` +In previous versions to react 19, the provider is only available as a method inside the context. From react 19, +this is still possible, but only as legacy. We prefer to use the new approach. + +```jsx +import React from "react"; + +const MyContext = React.createContext({ + username: "", + setUsername: () => {}, +}); + +export const MyContextProvider = (props) => { + const [username, setUsername] = React.useState("John Doe"); + + return ( + // MyContext.Provider is legacy + + {props.children} + + ); +}; +``` + Check out what we have here: - We have a component that provides state to our context. @@ -158,7 +181,7 @@ _./src/demo.tsx_ ```diff export const MyComponent = () => { -+ const myContext = React.useContext(MyContext); ++ const myContext = React.use(MyContext); return ( <> @@ -168,6 +191,7 @@ export const MyComponent = () => { ) } ``` + - If we execute the example we can see it working: ```bash diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme_es.md b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme_es.md index 41e333dfb..2f79918aa 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme_es.md @@ -69,7 +69,9 @@ React incorpora un mecanismo muy potente, se llama **Context** o de por ejemplo una ventana que contenga varios tabs. Y a todo esto tenemos que añadirle que React incorpora un hook que se llama -_useContext_ que hace que usarlo sea muy facil. +_use_ que hace que usarlo sea muy facil. + +**En versiones anteriores a la 19, usar _usecontext_ para consumir contextos** Vamos a ver como funciona esto. @@ -122,13 +124,36 @@ const MyContext = React.createContext({ + const [username, setUsername] = React.useState("John Doe"); + + return ( -+ ++ + {props.children} -+ ++ + ); + }; ``` +En versiones anteriores de react 19, el provider está disponible como método dentro de MyContext. En la versión 19 +sigue siendo posible usarlo, aunque se considera legacy. Nosotros nos quedamos con la nueva versión. + +```jsx +import React from "react"; + +const MyContext = React.createContext({ + username: "", + setUsername: () => {}, +}); + +export const MyContextProvider = (props) => { + const [username, setUsername] = React.useState("John Doe"); + + return ( + // MyContext.Provider is legacy + + {props.children} + + ); +}; +``` + Fijate lo que tenemos aqui: - Tenemos un componente que provee de estado a nuestro contexto. @@ -181,7 +206,7 @@ hay debajo del contextprovider lo pinta tal cual ese componente. ```diff export const MyComponent = () => { -+ const myContext = React.useContext(MyContext); ++ const myContext = React.use(MyContext); return ( <> diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/src/index.html b/04-frameworks/01-react/03-react-hooks/11-use-context/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/11-use-context/src/index.html rename to 04-frameworks/01-react/03-react-hooks/11-use-context/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/package.json b/04-frameworks/01-react/03-react-hooks/11-use-context/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/package.json +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/11-use-context/src/demo.tsx index 64134de6c..766e3c846 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/src/demo.tsx +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/src/demo.tsx @@ -14,9 +14,7 @@ export const MyContextProvider = (props) => { const [username, setUsername] = React.useState("John Doe"); return ( - - {props.children} - + {props.children} ); }; diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/tsconfig.json b/04-frameworks/01-react/03-react-hooks/11-use-context/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/vite.config.ts b/04-frameworks/01-react/03-react-hooks/11-use-context/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/webpack.config.js b/04-frameworks/01-react/03-react-hooks/11-use-context/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 6f7b30f7a78999087233e50b37b0e4bdacc8c14c Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 21:57:17 +0200 Subject: [PATCH 24/31] refactor react 19 - vite --- .../03-react-hooks/07-custom-hook/src/app.tsx | 6 --- .../07-custom-hook/src/demo.tsx | 33 ------------ .../07-custom-hook/src/index.tsx | 8 --- .../07-custom-hook/src/styles.css | 3 -- .../03-react-hooks/12-set-state-func/.babelrc | 7 --- .../12-set-state-func/{src => }/index.html | 9 ++-- .../12-set-state-func/package.json | 47 ++++++---------- .../12-set-state-func/tsconfig.json | 25 ++++----- .../12-set-state-func/vite.config.ts | 7 +++ .../12-set-state-func/webpack.config.js | 54 ------------------- .../03-react-hooks/13-async-closure/.babelrc | 7 --- .../13-async-closure/{src => }/index.html | 9 ++-- .../13-async-closure/package.json | 47 ++++++---------- .../13-async-closure/tsconfig.json | 25 ++++----- .../13-async-closure/vite.config.ts | 7 +++ .../13-async-closure/webpack.config.js | 54 ------------------- .../03-react-hooks/14-use-ref-dom/.babelrc | 7 --- .../src => 14-use-ref-dom}/index.html | 9 ++-- .../14-use-ref-dom/package.json | 47 ++++++---------- .../14-use-ref-dom/tsconfig.json | 25 ++++----- .../14-use-ref-dom/vite.config.ts | 7 +++ .../14-use-ref-dom/webpack.config.js | 54 ------------------- .../03-react-hooks/15-memo-predicate/.babelrc | 7 --- .../src => 15-memo-predicate}/index.html | 9 ++-- .../15-memo-predicate/package.json | 47 ++++++---------- .../15-memo-predicate/tsconfig.json | 25 ++++----- .../15-memo-predicate/vite.config.ts | 7 +++ .../15-memo-predicate/webpack.config.js | 54 ------------------- .../16-use-debug-value/.babelrc | 7 --- .../16-use-debug-value/index.html | 13 +++++ .../16-use-debug-value/package.json | 47 ++++++---------- .../16-use-debug-value/src/index.html | 12 ----- .../16-use-debug-value/tsconfig.json | 25 ++++----- .../16-use-debug-value/vite.config.ts | 7 +++ .../16-use-debug-value/webpack.config.js | 54 ------------------- 35 files changed, 208 insertions(+), 603 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css delete mode 100644 04-frameworks/01-react/03-react-hooks/12-set-state-func/.babelrc rename 04-frameworks/01-react/03-react-hooks/12-set-state-func/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/12-set-state-func/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/12-set-state-func/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/13-async-closure/.babelrc rename 04-frameworks/01-react/03-react-hooks/13-async-closure/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/13-async-closure/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/13-async-closure/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/14-use-ref-dom/.babelrc rename 04-frameworks/01-react/03-react-hooks/{15-memo-predicate/src => 14-use-ref-dom}/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/14-use-ref-dom/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/14-use-ref-dom/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/15-memo-predicate/.babelrc rename 04-frameworks/01-react/03-react-hooks/{14-use-ref-dom/src => 15-memo-predicate}/index.html (55%) create mode 100644 04-frameworks/01-react/03-react-hooks/15-memo-predicate/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/15-memo-predicate/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/16-use-debug-value/.babelrc create mode 100644 04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html delete mode 100644 04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/16-use-debug-value/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/16-use-debug-value/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx deleted file mode 100644 index bc2cf5bd8..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; -import { MyComponent } from "./demo"; - -export const App = () => { - return ; -}; diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx deleted file mode 100644 index 5c43159de..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; - -const useUserCollection = () => { - const [filter, setFilter] = React.useState(""); - const [userCollection, setUserCollection] = React.useState([]); - - // Load full list when the component gets mounted and filter gets updated - const loadUsers = () => - fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) - .then((response) => response.json()) - .then((json) => setUserCollection(json)); - - return { userCollection, loadUsers, filter, setFilter }; -}; - -export const MyComponent = () => { - const { userCollection, loadUsers, filter, setFilter } = useUserCollection(); - - React.useEffect(() => { - loadUsers(); - }, [filter]); - - return ( -
- setFilter(e.target.value)} /> -
    - {userCollection.map((user, index) => ( -
  • {user.name}
  • - ))} -
-
- ); -}; diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx deleted file mode 100644 index 7e439b87e..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -const container = document.getElementById("root"); -const root = createRoot(container); - -root.render(); diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css deleted file mode 100644 index 74dc08fbb..000000000 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.my-text { - color: blue; -} diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/.babelrc b/04-frameworks/01-react/03-react-hooks/12-set-state-func/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/src/index.html b/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/12-set-state-func/src/index.html rename to 04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/package.json b/04-frameworks/01-react/03-react-hooks/12-set-state-func/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/package.json +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/tsconfig.json b/04-frameworks/01-react/03-react-hooks/12-set-state-func/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/vite.config.ts b/04-frameworks/01-react/03-react-hooks/12-set-state-func/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/webpack.config.js b/04-frameworks/01-react/03-react-hooks/12-set-state-func/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/.babelrc b/04-frameworks/01-react/03-react-hooks/13-async-closure/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/src/index.html b/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/13-async-closure/src/index.html rename to 04-frameworks/01-react/03-react-hooks/13-async-closure/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/package.json b/04-frameworks/01-react/03-react-hooks/13-async-closure/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/package.json +++ b/04-frameworks/01-react/03-react-hooks/13-async-closure/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/tsconfig.json b/04-frameworks/01-react/03-react-hooks/13-async-closure/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/13-async-closure/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/vite.config.ts b/04-frameworks/01-react/03-react-hooks/13-async-closure/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/13-async-closure/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/webpack.config.js b/04-frameworks/01-react/03-react-hooks/13-async-closure/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/.babelrc b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.html b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.html rename to 04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/package.json b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/package.json +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/tsconfig.json b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/vite.config.ts b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/webpack.config.js b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/.babelrc b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/src/index.html b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/14-use-ref-dom/src/index.html rename to 04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/package.json b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/package.json +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/tsconfig.json b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/vite.config.ts b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/webpack.config.js b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/.babelrc b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/package.json b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/package.json +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.html b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/tsconfig.json b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/vite.config.ts b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/webpack.config.js b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 316a9187758b38e7bfde6697001116f760c37ab7 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 22:26:08 +0200 Subject: [PATCH 25/31] correction --- .../03-react-hooks/15-memo-predicate/Readme.md | 13 ------------- .../03-react-hooks/15-memo-predicate/src/index.tsx | 1 + .../03-react-hooks/16-use-debug-value/src/index.tsx | 1 + 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/Readme.md b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/Readme.md index ba8d8c3e4..e96333d34 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/Readme.md @@ -12,19 +12,6 @@ We are going to implement a customer satisfaction widget, based on smily faces, npm install ``` -- We have to make a slight change in this example in our _webpack.config.js_ - -```diff -... - { - test: /\.(png|jpg)$/, - exclude: /node_modules/, -- loader: "url-loader", -+ type: "asset/resource", - }, -... -``` - - Let's copy the five smiley faces (you can copy them from the sample implementation in github) into the route _src/assets_. - Let's add the following content into the _src/styles.css_ css file to add the smileys styles: diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.tsx b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.tsx +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.tsx b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.tsx +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); From 8e90d02cd9bf459656c928ad409c14d92ff7943d Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 22:41:39 +0200 Subject: [PATCH 26/31] corrections --- .../05-component-update-render/src/index.html | 12 ----- .../03-react-hooks/07-custom-hook/src/app.tsx | 6 +++ .../07-custom-hook/src/demo.tsx | 33 ++++++++++++ .../07-custom-hook/src/index.tsx | 8 +++ .../07-custom-hook/src/styles.css | 3 ++ .../17-why-did-you-update/.babelrc | 7 --- .../src => 17-why-did-you-update}/index.html | 9 ++-- .../17-why-did-you-update/package.json | 47 ++++++---------- .../17-why-did-you-update/src/demo.tsx | 2 +- .../17-why-did-you-update/src/index.html | 12 ----- .../17-why-did-you-update/tsconfig.json | 25 ++++----- .../17-why-did-you-update/vite.config.ts | 7 +++ .../17-why-did-you-update/webpack.config.js | 54 ------------------- .../99-promise-unmounted-R17/.babelrc | 7 --- .../index.html | 9 ++-- .../99-promise-unmounted-R17/package.json | 47 ++++++---------- .../99-promise-unmounted-R17/src/index.html | 12 ----- .../99-promise-unmounted-R17/tsconfig.json | 25 ++++----- .../99-promise-unmounted-R17/vite.config.ts | 7 +++ .../webpack.config.js | 54 ------------------- 20 files changed, 131 insertions(+), 255 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/src/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx create mode 100644 04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css delete mode 100644 04-frameworks/01-react/03-react-hooks/17-why-did-you-update/.babelrc rename 04-frameworks/01-react/03-react-hooks/{03-component-mount/src => 17-why-did-you-update}/index.html (55%) delete mode 100644 04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/17-why-did-you-update/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/17-why-did-you-update/webpack.config.js delete mode 100644 04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/.babelrc rename 04-frameworks/01-react/03-react-hooks/{04-component-unmount/src => 99-promise-unmounted-R17}/index.html (55%) delete mode 100644 04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/src/index.html create mode 100644 04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/index.html b/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx new file mode 100644 index 000000000..363d30bfa --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/app.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import { MyComponent } from "./demo"; + +export const App = () => { + return ; +}; \ No newline at end of file diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx new file mode 100644 index 000000000..5c43159de --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/demo.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +const useUserCollection = () => { + const [filter, setFilter] = React.useState(""); + const [userCollection, setUserCollection] = React.useState([]); + + // Load full list when the component gets mounted and filter gets updated + const loadUsers = () => + fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) + .then((response) => response.json()) + .then((json) => setUserCollection(json)); + + return { userCollection, loadUsers, filter, setFilter }; +}; + +export const MyComponent = () => { + const { userCollection, loadUsers, filter, setFilter } = useUserCollection(); + + React.useEffect(() => { + loadUsers(); + }, [filter]); + + return ( +
+ setFilter(e.target.value)} /> +
    + {userCollection.map((user, index) => ( +
  • {user.name}
  • + ))} +
+
+ ); +}; diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx new file mode 100644 index 000000000..7e439b87e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/index.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; + +const container = document.getElementById("root"); +const root = createRoot(container); + +root.render(); diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css new file mode 100644 index 000000000..74dc08fbb --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/src/styles.css @@ -0,0 +1,3 @@ +.my-text { + color: blue; +} diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/.babelrc b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.html b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.html rename to 04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/03-component-mount/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/package.json b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/package.json +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/demo.tsx b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/demo.tsx index 1ce9a88cb..7c2886cc9 100644 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/demo.tsx +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/demo.tsx @@ -4,7 +4,7 @@ import React from "react"; function useWhyDidYouUpdate(name, props) { // Get a mutable ref object where we can store props ... // ... for comparison next time this hook runs. - const previousProps = React.useRef(); + const previousProps = React.useRef(null); React.useEffect(() => { if (previousProps.current) { diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/index.html b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/tsconfig.json b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/vite.config.ts b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/webpack.config.js b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/.babelrc b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.html b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html similarity index 55% rename from 04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.html rename to 04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/package.json b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/package.json index d434b896c..9ee970f00 100644 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/package.json +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/package.json @@ -1,40 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "use-debounce": "^8.0.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/src/index.html b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/tsconfig.json b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/tsconfig.json +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/vite.config.ts b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/webpack.config.js b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 2f840dce22857c81cff43492145bdd1403f91f40 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Mon, 1 Sep 2025 23:07:10 +0200 Subject: [PATCH 27/31] refactor react 19 - vite - basic app --- .../03-react-hooks/00-boilerplate/src/app.tsx | 5 + .../00-boilerplate/src/index.ts | 1 - .../00-boilerplate/src/index.tsx | 8 ++ .../04-basic-app/00-boiler-plate/.babelrc | 7 - .../src => 00-boiler-plate}/index.html | 9 +- .../04-basic-app/00-boiler-plate/package.json | 46 +++---- .../04-basic-app/00-boiler-plate/readme.md | 120 +----------------- .../04-basic-app/00-boiler-plate/readme_es.md | 112 +--------------- .../00-boiler-plate/src/index.tsx | 5 +- .../00-boiler-plate/tsconfig.json | 25 ++-- .../00-boiler-plate/vite.config.ts | 7 + .../00-boiler-plate/webpack.config.js | 54 -------- .../01-react/04-basic-app/01-routing/.babelrc | 7 - .../{02-login/src => 01-routing}/index.html | 9 +- .../04-basic-app/01-routing/package.json | 48 +++---- .../04-basic-app/01-routing/src/index.tsx | 1 + .../04-basic-app/01-routing/tsconfig.json | 25 ++-- .../04-basic-app/01-routing/vite.config.ts | 7 + .../04-basic-app/01-routing/webpack.config.js | 58 --------- .../01-react/04-basic-app/02-login/.babelrc | 7 - .../src => 02-login}/index.html | 9 +- .../04-basic-app/02-login/package.json | 48 +++---- .../04-basic-app/02-login/src/index.tsx | 1 + .../04-basic-app/02-login/tsconfig.json | 25 ++-- .../04-basic-app/02-login/vite.config.ts | 7 + .../04-basic-app/02-login/webpack.config.js | 58 --------- .../01-react/04-basic-app/03-list/.babelrc | 7 - .../04-basic-app/03-list/{src => }/index.html | 9 +- .../04-basic-app/03-list/package.json | 48 +++---- .../04-basic-app/03-list/src/index.tsx | 1 + .../04-basic-app/03-list/tsconfig.json | 25 ++-- .../04-basic-app/03-list/vite.config.ts | 7 + .../04-basic-app/03-list/webpack.config.js | 58 --------- .../01-react/04-basic-app/04-detail/.babelrc | 7 - .../04-basic-app/04-detail/index.html | 13 ++ .../04-basic-app/04-detail/package.json | 48 +++---- .../04-basic-app/04-detail/src/index.html | 12 -- .../04-basic-app/04-detail/src/index.tsx | 1 + .../04-basic-app/04-detail/tsconfig.json | 25 ++-- .../04-basic-app/04-detail/vite.config.ts | 7 + .../04-basic-app/04-detail/webpack.config.js | 58 --------- 41 files changed, 243 insertions(+), 792 deletions(-) create mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts create mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx delete mode 100644 04-frameworks/01-react/04-basic-app/00-boiler-plate/.babelrc rename 04-frameworks/01-react/04-basic-app/{01-routing/src => 00-boiler-plate}/index.html (55%) create mode 100644 04-frameworks/01-react/04-basic-app/00-boiler-plate/vite.config.ts delete mode 100644 04-frameworks/01-react/04-basic-app/00-boiler-plate/webpack.config.js delete mode 100644 04-frameworks/01-react/04-basic-app/01-routing/.babelrc rename 04-frameworks/01-react/04-basic-app/{02-login/src => 01-routing}/index.html (55%) create mode 100644 04-frameworks/01-react/04-basic-app/01-routing/vite.config.ts delete mode 100644 04-frameworks/01-react/04-basic-app/01-routing/webpack.config.js delete mode 100644 04-frameworks/01-react/04-basic-app/02-login/.babelrc rename 04-frameworks/01-react/04-basic-app/{00-boiler-plate/src => 02-login}/index.html (55%) create mode 100644 04-frameworks/01-react/04-basic-app/02-login/vite.config.ts delete mode 100644 04-frameworks/01-react/04-basic-app/02-login/webpack.config.js delete mode 100644 04-frameworks/01-react/04-basic-app/03-list/.babelrc rename 04-frameworks/01-react/04-basic-app/03-list/{src => }/index.html (55%) create mode 100644 04-frameworks/01-react/04-basic-app/03-list/vite.config.ts delete mode 100644 04-frameworks/01-react/04-basic-app/03-list/webpack.config.js delete mode 100644 04-frameworks/01-react/04-basic-app/04-detail/.babelrc create mode 100644 04-frameworks/01-react/04-basic-app/04-detail/index.html delete mode 100644 04-frameworks/01-react/04-basic-app/04-detail/src/index.html create mode 100644 04-frameworks/01-react/04-basic-app/04-detail/vite.config.ts delete mode 100644 04-frameworks/01-react/04-basic-app/04-detail/webpack.config.js diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx new file mode 100644 index 000000000..f732c856e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/app.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export const App = () => { + return

Hello React !!

; +}; diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts deleted file mode 100644 index f69b4850f..000000000 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("Vite-boiler-plate"); diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx new file mode 100644 index 000000000..f323553ef --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./app"; + +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); + +root.render(); diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/.babelrc b/04-frameworks/01-react/04-basic-app/00-boiler-plate/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/04-basic-app/01-routing/src/index.html b/04-frameworks/01-react/04-basic-app/00-boiler-plate/index.html similarity index 55% rename from 04-frameworks/01-react/04-basic-app/01-routing/src/index.html rename to 04-frameworks/01-react/04-basic-app/00-boiler-plate/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/04-basic-app/01-routing/src/index.html +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/package.json b/04-frameworks/01-react/04-basic-app/00-boiler-plate/package.json index 50e9c4ccc..9ee970f00 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/package.json +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/package.json @@ -1,39 +1,23 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^19.1.0", + "react-dom": "^19.1.0" } } diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme.md b/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme.md index 1afae0061..6c71760df 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme.md +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme.md @@ -1,125 +1,17 @@ -# 03 Webpack React +# Boiler plate Vite React -## Summary +## Resumen -This example takes the _02-webpack-boiler_ example as a starting point. +We take the boiler plate from _./04-frameworks//01-react/02-base/02-vite-react_ -We will go step by step adding the necessary configuration so that we integrate -**React** into our build process. - -# Step by Step guide - -- First we copy the previous example, and do a _npm install_ - -```bash -npm install -``` - -- Let's install _react_ and _react-dom_ +- Check we left everything working: ```bash -npm install react react-dom --save +npm i ``` -- Let's install _react_ and _react-dom_ typings - -```bash -npm install @types/react @types/react-dom --save-dev -``` - -This way we have the React library and the bindings to integrate with a web browser. - -- In the index.html we are going to put the _div_ that will serve as entry point to instantiate our React application. our React application. - -_./src/index.html_ - -```diff - --

Hello World !

-+
- -``` - -- Let's create our first React component. - -_./src/app.tsx_ - -```tsx -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; -``` - -- It's time to instantiate that main component, to be able to integrate it with the browser we have to make use of _ReactDOM.render_. - -_./src/index.tsx_ - -```tsx -import React from "react"; -import ReactDOM from "react-dom"; -import { App } from "./app"; - -ReactDOM.render( -
- -
, - document.getElementById("root") -); -``` - -- We are on the right track, but if we try to run this it will fail, since _babel_ does not know how to transform the _jsx_ (remember that this was a sugar, which was actually an XML) into javaScript, in order for babel to be able to understand this we have to install the _preset_ _@babel/preset-react_ - -First we install it and the configure it. - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> By the way the _rc_ suffix is pretty usual in linux it's stands for "runcom" -> (CTSS system 1962-63) Script file containing startup instructions for an application program. -> In other words, "rc" is just something that stuck from back in the sixties, and has been used quite often for configuration files in different sorts of programs since, including Node, Babel and many, many others. -> More info [on stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Another curiosity... what is a _preset_ ... let's start with what is a babel plugin: babel transformations are -> enabled by applying plugins, there are plenty of plugins and if you have to go adding one by one it can become a nightmare, -> in order to make this easier, babel has grouped common sets of plugins in _presets_, for instance @babel-preset-react -> includes the following plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Is time to double check the _webpack.config.js_ - -- We can make sure that we have _ts_ and _tsx_ as valid extensions. -- Also that in the loader we accept both _ts_ and _tsx_. -- And in the app we have as entry point _index.tsx_. - -* Let's check that things are working as expected: +y ```bash npm start ``` - - - - - - - - - diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme_es.md b/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme_es.md index bb34f2812..937b4cf12 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme_es.md +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/readme_es.md @@ -1,118 +1,16 @@ -# 03 Webpack React +# Boiler plate Vite React ## Resumen -Este ejemplo toma como punto de partida el ejemplo _02-webpack-boiler_. +Tomamos el boiler plate de _./04-frameworks//01-react/02-base/02-vite-react_ -Vamos a ir paso a paso añdiendo la configuración necesaria para que integrar -**React** en nuestro proceso de build. - -## Paso a Paso - -- Primero copiamos el ejemplo anterior, y hacemos un _npm install_ - -```bash -npm install -``` - -- Vamos a instalar _react_ y _react-dom_ - -```bash -npm install react react-dom --save -``` - -- Vamos a instalarnos los typing de _react_ y _react-dom_ +- Vamos a comprobar que hemos dejado todo funcionando: ```bash -npm install @types/react @types/react-dom --save-dev -``` - -Así tenemos la librería de React y los bindings para que se integre con un navegador web. - -- En el index.html vamos a meter el _div_ que nos servirá como punto de entrada para instanciar - nuestra aplicación React. - -_./src/index.html_ - -```diff - --

Hello World !

-+
- -``` - -- Vamos a crear nuestro primero componente React. - -_./src/app.tsx_ - -```tsx -import React from "react"; - -export const App = () => { - return

Hello React !!

; -}; +npm i ``` -- Es hora de instanciar ese compente principal, para poder integrarlo con el navegador - tenemos que hacer uso a _ReactDOM.render_ - -_./src/index.tsx_ - -```tsx -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./app"; - -const container = document.getElementById("root"); -const root = createRoot(container); - -root.render(); -``` - -- Vamos por buen camino, pero si intentamos ejecutar esto no va fallar, ya que _babel_ no sabe - como transformar el _jsx_ (recordemos que esto era un azúcar, que en realidad era un XML) a - javaScript, para que babel sea capaz de entender esto tenemos que instalar el _preset_ - _@babel/preset-react_ - -Primero lo instalamos - -```bash -npm install @babel/preset-react --save-dev -``` - -_.babelrc_ - -```diff -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", -+ "@babel/preset-react" - ] -} -``` - -> Por cierto, el sufijo _rc_ es bastante habitual en linux, significa "runcom". -> (Sistema CTSS 1962-63) Archivo de script que contiene instrucciones de inicio para un programa de aplicación. -> En otras palabras, "rc" es algo que se quedó atrás en los años sesenta, y se ha utilizado con bastante frecuencia para los archivos de configuración en diferentes tipos de programas desde entonces, incluyendo Node, Babel y muchos, muchos otros. -> Más información [en stackoverflow](https://stackoverflow.com/questions/36212256/what-are-rc-files-in-nodejs). - -> Otra curiosidad... qué es un _preset_ ... empecemos por lo que es un plugin de babel: las transformaciones de babel -> se habilitan aplicando plugins, hay un montón de plugins y si tienes que ir añadiendo uno a uno se puede convertir en una pesadilla, -> para hacer esto más fácil, babel ha agrupado conjuntos comunes de plugins en _presets_, por ejemplo @babel-preset-react -> incluye los siguientes plugins: - -- @babel/plugin-syntax-jsx -- @babel/plugin-transform-react-jsx -- @babel/plugin-transform-react-display-name - -- Es hora de saltar al _webpack.config.js_ - -- Nos podemos asegurar de que tenemos como extension valida _ts_ y _tsx_ -- También que en el loader aceptamos tanto _ts_ como _tsx_ -- Y en el app tenemos como punto de entrada _index.tsx_ - -* Vamos a comprobar que hemos dejado todo funcionando: +y ```bash npm start diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.tsx b/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.tsx index 7e439b87e..1b533b96d 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.tsx +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.tsx @@ -1,8 +1,9 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; -const container = document.getElementById("root"); -const root = createRoot(container); +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); root.render(); diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/tsconfig.json b/04-frameworks/01-react/04-basic-app/00-boiler-plate/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/tsconfig.json +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/vite.config.ts b/04-frameworks/01-react/04-basic-app/00-boiler-plate/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/00-boiler-plate/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/webpack.config.js b/04-frameworks/01-react/04-basic-app/00-boiler-plate/webpack.config.js deleted file mode 100644 index 326060f82..000000000 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/04-basic-app/01-routing/.babelrc b/04-frameworks/01-react/04-basic-app/01-routing/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/04-basic-app/01-routing/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/04-basic-app/02-login/src/index.html b/04-frameworks/01-react/04-basic-app/01-routing/index.html similarity index 55% rename from 04-frameworks/01-react/04-basic-app/02-login/src/index.html rename to 04-frameworks/01-react/04-basic-app/01-routing/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/04-basic-app/02-login/src/index.html +++ b/04-frameworks/01-react/04-basic-app/01-routing/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/04-basic-app/01-routing/package.json b/04-frameworks/01-react/04-basic-app/01-routing/package.json index 880a61213..360ceb19a 100644 --- a/04-frameworks/01-react/04-basic-app/01-routing/package.json +++ b/04-frameworks/01-react/04-basic-app/01-routing/package.json @@ -1,40 +1,24 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-router-dom": "^6.3.0" + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.8.2" } } diff --git a/04-frameworks/01-react/04-basic-app/01-routing/src/index.tsx b/04-frameworks/01-react/04-basic-app/01-routing/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/04-basic-app/01-routing/src/index.tsx +++ b/04-frameworks/01-react/04-basic-app/01-routing/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/04-basic-app/01-routing/tsconfig.json b/04-frameworks/01-react/04-basic-app/01-routing/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/04-basic-app/01-routing/tsconfig.json +++ b/04-frameworks/01-react/04-basic-app/01-routing/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/04-basic-app/01-routing/vite.config.ts b/04-frameworks/01-react/04-basic-app/01-routing/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/01-routing/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/04-basic-app/01-routing/webpack.config.js b/04-frameworks/01-react/04-basic-app/01-routing/webpack.config.js deleted file mode 100644 index 749d7f25d..000000000 --- a/04-frameworks/01-react/04-basic-app/01-routing/webpack.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - publicPath: "/", - }, - devServer: { - historyApiFallback: true, - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/04-basic-app/02-login/.babelrc b/04-frameworks/01-react/04-basic-app/02-login/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/04-basic-app/02-login/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.html b/04-frameworks/01-react/04-basic-app/02-login/index.html similarity index 55% rename from 04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.html rename to 04-frameworks/01-react/04-basic-app/02-login/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/04-basic-app/00-boiler-plate/src/index.html +++ b/04-frameworks/01-react/04-basic-app/02-login/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/04-basic-app/02-login/package.json b/04-frameworks/01-react/04-basic-app/02-login/package.json index 880a61213..360ceb19a 100644 --- a/04-frameworks/01-react/04-basic-app/02-login/package.json +++ b/04-frameworks/01-react/04-basic-app/02-login/package.json @@ -1,40 +1,24 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-router-dom": "^6.3.0" + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.8.2" } } diff --git a/04-frameworks/01-react/04-basic-app/02-login/src/index.tsx b/04-frameworks/01-react/04-basic-app/02-login/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/04-basic-app/02-login/src/index.tsx +++ b/04-frameworks/01-react/04-basic-app/02-login/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/04-basic-app/02-login/tsconfig.json b/04-frameworks/01-react/04-basic-app/02-login/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/04-basic-app/02-login/tsconfig.json +++ b/04-frameworks/01-react/04-basic-app/02-login/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/04-basic-app/02-login/vite.config.ts b/04-frameworks/01-react/04-basic-app/02-login/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/02-login/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/04-basic-app/02-login/webpack.config.js b/04-frameworks/01-react/04-basic-app/02-login/webpack.config.js deleted file mode 100644 index 749d7f25d..000000000 --- a/04-frameworks/01-react/04-basic-app/02-login/webpack.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - publicPath: "/", - }, - devServer: { - historyApiFallback: true, - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/04-basic-app/03-list/.babelrc b/04-frameworks/01-react/04-basic-app/03-list/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/04-basic-app/03-list/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/04-basic-app/03-list/src/index.html b/04-frameworks/01-react/04-basic-app/03-list/index.html similarity index 55% rename from 04-frameworks/01-react/04-basic-app/03-list/src/index.html rename to 04-frameworks/01-react/04-basic-app/03-list/index.html index a3d74b719..050566921 100644 --- a/04-frameworks/01-react/04-basic-app/03-list/src/index.html +++ b/04-frameworks/01-react/04-basic-app/03-list/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App +
+ diff --git a/04-frameworks/01-react/04-basic-app/03-list/package.json b/04-frameworks/01-react/04-basic-app/03-list/package.json index 880a61213..360ceb19a 100644 --- a/04-frameworks/01-react/04-basic-app/03-list/package.json +++ b/04-frameworks/01-react/04-basic-app/03-list/package.json @@ -1,40 +1,24 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-router-dom": "^6.3.0" + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.8.2" } } diff --git a/04-frameworks/01-react/04-basic-app/03-list/src/index.tsx b/04-frameworks/01-react/04-basic-app/03-list/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/04-basic-app/03-list/src/index.tsx +++ b/04-frameworks/01-react/04-basic-app/03-list/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/04-basic-app/03-list/tsconfig.json b/04-frameworks/01-react/04-basic-app/03-list/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/04-basic-app/03-list/tsconfig.json +++ b/04-frameworks/01-react/04-basic-app/03-list/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/04-basic-app/03-list/vite.config.ts b/04-frameworks/01-react/04-basic-app/03-list/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/03-list/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/04-basic-app/03-list/webpack.config.js b/04-frameworks/01-react/04-basic-app/03-list/webpack.config.js deleted file mode 100644 index 749d7f25d..000000000 --- a/04-frameworks/01-react/04-basic-app/03-list/webpack.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - publicPath: "/", - }, - devServer: { - historyApiFallback: true, - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; diff --git a/04-frameworks/01-react/04-basic-app/04-detail/.babelrc b/04-frameworks/01-react/04-basic-app/04-detail/.babelrc deleted file mode 100644 index 469d3d55f..000000000 --- a/04-frameworks/01-react/04-basic-app/04-detail/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-typescript", - "@babel/preset-react" - ] -} diff --git a/04-frameworks/01-react/04-basic-app/04-detail/index.html b/04-frameworks/01-react/04-basic-app/04-detail/index.html new file mode 100644 index 000000000..050566921 --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/04-detail/index.html @@ -0,0 +1,13 @@ + + + + + + React App + + + +
+ + + diff --git a/04-frameworks/01-react/04-basic-app/04-detail/package.json b/04-frameworks/01-react/04-basic-app/04-detail/package.json index 880a61213..360ceb19a 100644 --- a/04-frameworks/01-react/04-basic-app/04-detail/package.json +++ b/04-frameworks/01-react/04-basic-app/04-detail/package.json @@ -1,40 +1,24 @@ { - "name": "react-example", - "version": "1.0.0", - "description": "", - "main": "index.js", + "name": "hello-vite", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "start": "run-p -l type-check:watch start:dev", - "type-check": "tsc --noEmit", - "type-check:watch": "npm run type-check -- --watch", - "start:dev": "webpack-dev-server --mode development --open", - "build": "rimraf dist && webpack --mode development" + "start": "vite --host", + "build": "vite build", + "preview": "vite preview" }, - "author": "", - "license": "ISC", "devDependencies": { - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.16.7", - "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.4", - "babel-loader": "^8.2.5", - "css-loader": "^6.7.1", - "html-loader": "^3.1.0", - "html-webpack-plugin": "^5.5.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.72.1", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.9.0" + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-plugin-checker": "^0.10.0" }, "dependencies": { - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-router-dom": "^6.3.0" + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.8.2" } } diff --git a/04-frameworks/01-react/04-basic-app/04-detail/src/index.html b/04-frameworks/01-react/04-basic-app/04-detail/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/04-basic-app/04-detail/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - diff --git a/04-frameworks/01-react/04-basic-app/04-detail/src/index.tsx b/04-frameworks/01-react/04-basic-app/04-detail/src/index.tsx index 7e439b87e..7c541901b 100644 --- a/04-frameworks/01-react/04-basic-app/04-detail/src/index.tsx +++ b/04-frameworks/01-react/04-basic-app/04-detail/src/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { App } from "./app"; +import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container); diff --git a/04-frameworks/01-react/04-basic-app/04-detail/tsconfig.json b/04-frameworks/01-react/04-basic-app/04-detail/tsconfig.json index 3312b5f1e..a057cea1d 100644 --- a/04-frameworks/01-react/04-basic-app/04-detail/tsconfig.json +++ b/04-frameworks/01-react/04-basic-app/04-detail/tsconfig.json @@ -1,18 +1,19 @@ { "compilerOptions": { - "target": "es6", - "module": "es6", - "moduleResolution": "node", - "declaration": false, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, "noImplicitAny": false, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "jsx": "react", - "noLib": false, - "suppressImplicitAnyIndexErrors": true, + "noImplicitReturns": true, + "resolveJsonModule": true, "skipLibCheck": true, - "esModuleInterop": true + "sourceMap": true, + "target": "ESNext", + "useDefineForClassFields": true }, - "include": ["src/**/*"], - "exclude": ["node_modules"] + "include": ["src"] } diff --git a/04-frameworks/01-react/04-basic-app/04-detail/vite.config.ts b/04-frameworks/01-react/04-basic-app/04-detail/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/04-basic-app/04-detail/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [checker({ typescript: true }), react()], +}); diff --git a/04-frameworks/01-react/04-basic-app/04-detail/webpack.config.js b/04-frameworks/01-react/04-basic-app/04-detail/webpack.config.js deleted file mode 100644 index 749d7f25d..000000000 --- a/04-frameworks/01-react/04-basic-app/04-detail/webpack.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const path = require("path"); -const basePath = __dirname; - -module.exports = { - context: path.join(basePath, "src"), - resolve: { - extensions: [".js", ".ts", ".tsx"], - }, - entry: { - app: ["./index.tsx", "./styles.css"], - }, - devtool: "eval-source-map", - stats: "errors-only", - output: { - filename: "[name].[chunkhash].js", - publicPath: "/", - }, - devServer: { - historyApiFallback: true, - }, - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "babel-loader", - }, - { - test: /\.(png|jpg)$/, - type: "asset/resource", - }, - { - test: /\.html$/, - loader: "html-loader", - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: [ - { - loader: "style-loader", - }, - { - loader: "css-loader", - }, - ], - }, - ], - }, - plugins: [ - //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: "index.html", //Name of file in ./dist/ - template: "index.html", //Name of template in ./src - }), - ], -}; From 711efc15f911a5ab5c6d1f2b4e95a691239ed52e Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 06:44:00 +0200 Subject: [PATCH 28/31] 01-previous and 02-base - review --- .../01-previous/01-concepts/readme.md | 312 ++++++++++++++++++ .../01-previous/01-concepts/readme_es.md | 4 +- .../01-react/01-previous/02-basic/readme.md | 70 ++-- .../01-previous/02-basic/readme_es.md | 217 ++++++++++++ .../01-react/02-base/01-vite-boiler/README.md | 3 +- .../02-base/01-vite-boiler/readme_es.md | 3 +- .../01-react/02-base/02-vite-react/readme.md | 52 +-- .../02-base/02-vite-react/readme_es.md | 54 +-- .../01-react/02-base/03-list-users/readme.md | 9 +- .../02-base/03-list-users/readme_es.md | 16 +- .../02-base/04-list-refactor/readme.md | 9 +- .../02-base/04-list-refactor/readme_es.md | 10 +- .../{readme_en.md => readme.md} | 2 +- .../02-base/05-list-excercise/readme_es.md | 4 +- .../03-react-hooks/00-boilerplate/Readme.md | 1 - .../00-boilerplate/Readme_es.md | 1 - 16 files changed, 644 insertions(+), 123 deletions(-) create mode 100644 04-frameworks/01-react/01-previous/02-basic/readme_es.md rename 04-frameworks/01-react/02-base/05-list-excercise/{readme_en.md => readme.md} (87%) diff --git a/04-frameworks/01-react/01-previous/01-concepts/readme.md b/04-frameworks/01-react/01-previous/01-concepts/readme.md index e69de29bb..4fb3a2dae 100644 --- a/04-frameworks/01-react/01-previous/01-concepts/readme.md +++ b/04-frameworks/01-react/01-previous/01-concepts/readme.md @@ -0,0 +1,312 @@ +# 01 Previous - Hi React + +## Summary + +In this example we are going to create a _codesandbox_ to understand the first concepts of React and the main reasons why we need a library like this. +[Here you have the complete example that we are going to develop.](https://codesandbox.io/p/sandbox/react-concepts-rncyq4) + +To begin, we will start from a vanilla JavaScript project and gradually add features that bring us closer to the approach proposed by React. The goal is to see how React solves common web development problems in a more elegant and powerful way. + +## Step by step + +- Rename the file _index.mjs_ to _index.js_ and update the reference in _index.html_. +- Comment out all the content of _index.js_. +- In _index.html_ render a static list of users: + +_index.html_ + +```diff + + + + JavaScript Sandbox + + + + +-
++
++

Lista de usuarios

++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++
+ + + +``` + +This works, but frameworks like React offer us a different approach: they allow us to dynamically transform the DOM in the client. This way, the server only delivers a basic HTML along with a JavaScript file that generates the interface. + +We leave the HTML empty and move the list into our _index.js_: + +_index.html_ + +```diff + + + + JavaScript Sandbox + + + + ++
+-
+-

Lista de usuarios

+-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
+-
+ + + +``` + +_index.js_: + +```diff ++ import "./styles.css"; + ++ document.getElementById("app").innerHTML = ` ++

Lista de usuarios

++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++ `; +``` + +Now the content is generated by JavaScript. We can confirm that it’s the JavaScript file that generates the content. + +### Components + +Let’s start breaking our list into parts. First, we separate the title: + +```diff + import "./styles.css"; + ++ const Header = () => { ++ return `

Lista de usuarios

`; ++ }; ++ + document.getElementById("app").innerHTML = ` +-

Lista de usuarios

++ ${Header()} +
1955: Rick Sánchez
+
8765: Beth Harmon
+
7562: Farrokh Bulsara
+``` + +This function we just created, in React, is a component. That is, **in React, components are functions.** For now, this component returns a piece of our application, in this case the title, which renders something in the DOM. + +Let’s continue splitting or componentizing our application. We’ll create a new component that returns just the list.. + +```diff +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const List = () => { ++ return ` ++
++
1955: Rick Sánchez
++
8765: Beth Harmon
++
7562: Farrokh Bulsara
++
`; ++ }; + +document.getElementById("app").innerHTML = ` + ${Header()} +-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
++ ${List()} +`; +``` + +### Props + +Now let’s create a component that renders each user in the DOM. To do this, we’ll create a component (function) that receives a user object with an `id` and `name`: + +```diff +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const User = (props) => { ++ return `
${props.id}: ${props.name}
`; ++ }; + +const List = () => { + return ` +
++ ${User({id: 1955, name 'Rick Sánchez'})} ++ ${User({id: 8765, name 'Beth Harmon'})} ++ ${User({id: 7562, name 'Farrokh Bulsara'})} +-
1955: Rick Sánchez
+-
8765: Beth Harmon
+-
7562: Farrokh Bulsara
+
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; +``` + +In React jargon, the input arguments we pass to components are known as `props`. A bit later we’ll see that in React, the syntax for running a component is very different from this. However, it’s very important to keep in mind that even though the syntax is different, in the end what we’re doing is invoking functions and passing them input arguments. + +Let’s get a little closer to what a real application would do and simulate that the data we display in the list comes from an API. For this, let’s create a file _./api.js_. + +```js +export const getUsers = () => [ + { id: 1955, name: "Rick Sánchez" }, + { id: 8765, name: "Beth Harmon" }, + { id: 7562, name: "Farrokh Bulsara" }, +]; +``` + +When invoking it inside the `List` function, we can directly use a `map` method to execute the `User` function for each element of the array, no matter how many there are. + +```diff ++ import { getUsers } from './api'; +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + ++ const User = (props) => { ++ return `
${props.id}: ${props.name}
`; ++ }; + +const List = () => { ++ const users = getUsers(); + return ` +
++ ${users.map(user=>User(user)).join('')} +- ${User({id: 1955, name 'Rick Sánchez'})} +- ${User({id: 8765, name 'Beth Harmon'})} +- ${User({id: 7562, name 'Farrokh Bulsara'})} +
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; +``` + +In React, however, the `props` argument is a single parameter: an object to which I can pass whatever I want. Let’s adapt the code. + +```diff +import { getUsers } from "./api"; +import "./styles.css"; + +const Header = () => { + return `

Lista de usuarios

`; +}; + +- const User = (props) => { ++ const User = ({ user }) => { +- return `
${props.id}: ${props.name}
`; ++ return `
${user.id}: ${user.name}
`; +}; + +const List = () => { + const users = getUsers(); + return ` +
+- ${users.map((user) => User(user)).join("")} ++ ${users.map((user) => User({ user })).join("")} +
`; +}; + +document.getElementById("app").innerHTML = ` + ${Header()} + ${List()} +`; +``` + +### Reactivity + +Let’s try to render a random number for each element, calculated at the moment the component is invoked. + +```diff +const User = ({ user }) => { ++ const randomNumber = Math.random(); +- return `
${user.id}: ${user.name}
`; ++ return `
${user.id}: ${user.name} - ${randomNumber}
`; +}; +``` + +If we update it with a setTimeout, we see the value changes in the console, but the interface does not update: + +```diff +const User = ({ user }) => { +- const randomNumber = Math.random(); ++ let randomNumber = Math.random(); ++ setTimeout(() => { ++ randomNumber = Math.random(); ++ console.log(randomNumber); ++ }, 3000); + return `
${user.id}: ${user.name} - ${randomNumber}
`; +}; +``` + +Why doesn’t the interface refresh after the three seconds of the setTimeout? Try to think of the answer... + +The explanation is simple: functions are executed only once. At that moment they return something that generates a fragment of HTML. That initial result is what gets injected into the DOM and doesn’t change again, even though the internal logic of the function (like the value of `randomNumber`) does get updated later. + +If we look at the console, we see that the value of `randomNumber` is indeed recalculated, but the interface doesn’t reflect that change. This happens because the DOM is not automatically linked to the data of our application. + +And this is where libraries like React come in. Their main value is that they incorporate reactivity: they allow us to keep the application state and the user interface in sync. + +In React, states are the key piece to persist and manage data. Every time a state changes, React re-executes the components that depend on it, ensuring the interface updates and stays aligned with the most recent information. + +### Events and persistence + +```diff +const List = () => { +- const users = getUsers(); ++ let users = getUsers(); + ++ const handleClick = () => { ++ alert("button clicked!"); ++ users = [...users, { id: 1234, name: "John Doe" }]; ++ }; + + return ` +
+ ${users.map((user) => User({ user })).join("")} ++ +
`; +}; +``` + +The button appears but when clicking it, not even the alert shows up. What’s going on? +Again, when `List` is executed, the `handleClick` function is created. However, that function doesn’t run until we click the button, and when that happens, the function no longer exists, because the `List` function has already executed and died. + +This is another problem React solves, since it allows us to persist data and functions between executions of our components. + +To leave the example ready for the next exercise, let’s make the following change: + +```diff ++ export default function App() { ++ return ` ++ ${Header()} ++ ${List()} ++ `; +} + ++ document.getElementById("app").innerHTML = App(); +- document.getElementById("app").innerHTML = ` +- ${Header()} +- ${List()} +- `; +``` diff --git a/04-frameworks/01-react/01-previous/01-concepts/readme_es.md b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md index 2f03fd513..01b70766e 100644 --- a/04-frameworks/01-react/01-previous/01-concepts/readme_es.md +++ b/04-frameworks/01-react/01-previous/01-concepts/readme_es.md @@ -63,7 +63,7 @@ _index.html_ ``` -Yn en _index.js_: +Y en _index.js_: ```diff + import "./styles.css"; @@ -202,7 +202,7 @@ document.getElementById("app").innerHTML = ` `; ``` -En react sin embargo el argumento `props` es un único parámetro, un objeto al que voy a poder pasarle todo lo que quiera. Adaptamos el código. +En react sin embargo el argumento `props` es un único parámetro, un objeto al que voy a poder pasar todo lo que quiera. Adaptamos el código. ```diff import { getUsers } from "./api"; diff --git a/04-frameworks/01-react/01-previous/02-basic/readme.md b/04-frameworks/01-react/01-previous/02-basic/readme.md index 42351d280..939a1d2ee 100644 --- a/04-frameworks/01-react/01-previous/02-basic/readme.md +++ b/04-frameworks/01-react/01-previous/02-basic/readme.md @@ -1,8 +1,8 @@ -# 01 Basic - Hola React +# 01 Basic - Hi React -Vamos a migrar la aplicación en Javascript de _01-concepts_ a react. [Aquí tenéis el ejemplo completo que vamos a desarrollar](https://codesandbox.io/p/sandbox/react-basic-h9rhkk) Para ello vamos a crearnos un codesandbox de react. +We are going to migrate the JavaScript application from _01-concepts_ ato react. [Here you have the complete example we are going to develop](https://codesandbox.io/p/sandbox/react-basic-h9rhkk) For this, we’ll create a React codesandbox.. -Creamos el mismo fichero _./api_ +We create the same file _./api.js_ ```js export const getUsers = () => [ @@ -12,13 +12,13 @@ export const getUsers = () => [ ]; ``` -A continuación, desde el ejemplo que hemos dejado preparado en _01-concepts_ vamos a copiar y pegar _index.js_. Vamos a cambiar únicamente lo que devuelve cada uno de los componentes. El motivo es que en react, los componentes devuelven elementos `jsx`, que no es más que azucar sintáctico de javascript. +Next, from the example we left ready in _01-concepts_, we are going to copy and paste _index.js_. We are only going to change what each of the components returns. The reason is that in React, components return `jsx` elements, which is nothing more than syntactic sugar for JavaScript. -**Reemplazamos literales por elementos jsx en los componentes:** +**We replace string literals with jsx elements in the components:** -Por ejemplo, en el componente `Header`: +For example in the `Header` component: -- En código Javascript: +- In Javascript: ```js const Header = () => { @@ -26,7 +26,7 @@ const Header = () => { }; ``` -- En código React: +- In React: ```jsx const Header = () => { @@ -34,7 +34,7 @@ const Header = () => { }; ``` -Si aplicamos el mismo tipo de cambio en el resto de componentes, el fichero _index.jsx_ nos tendría que quedar así: +If we apply the same type of change in the rest of the components, the index.jsx file should look like this: ```jsx import React from "react"; @@ -75,10 +75,10 @@ export default function App() { } ``` -Comprobamos que nuestra aplicación renderiza la lista por la pantalla. +We check that our application renders the list on the screen. -**Sintaxis React** -En React vamos a poder usar la sintaxis jsx cuando invocamos nuestros componentes: +**React syntax** +In React we are able to use `jsx` syntax when we invoke our components: ```diff export default function App() { @@ -93,7 +93,7 @@ export default function App() { } ``` -Además, si queremos pasar un argumento por props (argumentos de entrada a nuestro componente): +Also, if we want to pass an argument through props (the input arguments to our component): ```diff const List = () => { @@ -103,7 +103,7 @@ const List = () => { }; ``` -Al hacer esto, la consola nos va a lanzar un error que aparece cuando renderizamos elementos iterando por una lista. Como vemos en la traza, nos pide que le pasemos al componente una key con valor único (ya veremos más adelante a que se debe): +When doing this, the console will throw an error that appears when we render elements by iterating over a list. As we can see in the trace, it asks us to pass the component a unique `key` value (later on we’ll see why this is necessary): ```diff const List = () => { @@ -113,7 +113,7 @@ const List = () => { }; ``` -Pero Como estamos viendo la variable `randomNumber` sigue estando desincronizada de nuestra interfaz de usuario. Esto se debe a que no estamos guardando ese valor en un estado, por lo que react no se entera del cambio. Para que nuestra aplicación sea reactiva hacemos el siguiente cambio: +But as we can see, the `randomNumber` variable is still out of sync with our user interface. This happens because we are not storing that value in state, so React doesn’t know about the change. To make our application reactive, we make the following change: ```diff const User = ({ user }) => { @@ -136,24 +136,24 @@ setTimeout(() => { }; ``` -Si nos fijamos vemos, que a pesar de que es un setTimeout (debería ejecutarse una sola vez), se está ejecutando cada tres segundos ¿Por qué? +If we look closely, we see that even though it’s a setTimeout (which should execute only once), it’s actually running every three seconds. Why? -En el código, el setTimeout está dentro del cuerpo del componente. Eso significa que cada vez que el componente se re-ejecuta, React vuelve a crear un nuevo setTimeout. +In the code, the setTimeout is inside the body of the component. That means every time the component re-renders, React creates a new setTimeout. -Cuando el setTimeout se cumple, llama a setRandomNumber, lo cual cambia el estado. Ese cambio de estado provoca un nuevo renderizado, y en ese nuevo renderizado se vuelve a crear otro setTimeout. Así entras en un bucle infinito: +When the setTimeout finishes, it calls setRandomNumber, which changes the state. That state change triggers a new render, and in that render a new setTimeout is created again. This creates an infinite loop: -1. ejecución/render → crea setTimeout. -2. setTimeout → randomNumber cambia estado. -3. React detecta cambio de estado → React ejecuta componente de nuevo. -4. Vuelve al paso 1. +1. Execution/render → creates setTimeout. +2. SetTimeout → randomNumber changes state. +3. React detects state change → React re-renders component. +4. Back to step 1. -La clave: no es que el setTimeout se repita automáticamente, sino que se vuelve a crear en cada ejecución. +The key: it’s not that the setTimeout repeats automatically, but that it gets recreated on every execution. -Cuando escribimos lógica directamente dentro de un componente de React, esa lógica se va a ejecutar en cada renderizado. Esto puede generar problemas de rendimiento o incluso bucles infinitos (como en el caso de setTimeout, que se vuelve a crear en cada render). +When we write logic directly inside a React component, that logic will run on every render. This can cause performance issues, application errors, or even infinite loops (like in this setTimeout case, which gets recreated every render). -Para controlar cuándo y con qué condiciones se ejecuta cierto código, React nos proporciona el hook `useEffect`, que nos permite manejar efectos secundarios (side effects), como temporizadores, peticiones a APIs o suscripciones a eventos, de forma controlada. +To control when and under what conditions some code executes, React gives us the useEffect hook, which allows us to manage side effects (like timers, API requests, or event subscriptions) in a controlled way. -Su sintaxis es la siguiente: +Its syntax is: ```jsx useEffect(() => { @@ -161,18 +161,18 @@ useEffect(() => { }, [dependencias]); ``` -Parámetros de useEffect: +Parameters of useEffect: -- Callback (efecto): la función que queremos ejecutar. -- Lista de dependencias: un array que indica cuándo debe volver a ejecutarse ese callback. +- Callback (effect): the function we want to execute. +- Dependency list: an array that tells React when to re-run the callback. -Ejemplos: +Examples: -- [] → el efecto solo se ejecuta una vez, cuando el componente se monta. -- [estado] → el efecto se ejecuta cada vez que cambia estado. -- undefined → el efecto se ejecuta en cada renderizado. (evitar) +- [] → the effect runs only once, when the component mounts. +- [state] → the effect runs every time that state changes. +- undefined → the effect runs on every render. -Así, usamos `useEffect` con un array de depencias vacio, porque queremos que el `setTimeout` se ejecute una sola vez, cuando se crea el componente: +So, we use `useEffect` with an empty dependency array, because we want the setTimeout to run only once, when the component is created: ```diff const User = ({ user }) => { @@ -193,7 +193,7 @@ setTimeout(() => { }; ``` -Vamos a crear ahora un button que al clicar, me añada un nuevo elemento a la lista: +Now let’s create a button that, when clicked, adds a new element to the list: ```diff const List = () => { diff --git a/04-frameworks/01-react/01-previous/02-basic/readme_es.md b/04-frameworks/01-react/01-previous/02-basic/readme_es.md new file mode 100644 index 000000000..e8660f13b --- /dev/null +++ b/04-frameworks/01-react/01-previous/02-basic/readme_es.md @@ -0,0 +1,217 @@ +# 01 Basic - Hola React + +Vamos a migrar la aplicación en Javascript de _01-concepts_ a react. [Aquí tenéis el ejemplo completo que vamos a desarrollar](https://codesandbox.io/p/sandbox/react-basic-h9rhkk) Para ello vamos a crearnos un codesandbox de react. + +Creamos el mismo fichero _./api.js_ + +```js +export const getUsers = () => [ + { id: 1955, name: "Rick Sánchez" }, + { id: 8765, name: "Beth Harmon" }, + { id: 7562, name: "Farrokh Bulsara" }, +]; +``` + +A continuación, desde el ejemplo que hemos dejado preparado en _01-concepts_ vamos a copiar y pegar _index.js_. Vamos a cambiar únicamente lo que devuelve cada uno de los componentes. El motivo es que en react, los componentes devuelven elementos `jsx`, que no es más que azúcar sintáctico de javascript. + +**Reemplazamos literales por elementos jsx en los componentes:** + +Por ejemplo, en el componente `Header`: + +- En código Javascript: + +```js +const Header = () => { + return `

Lista de usuarios

`; +}; +``` + +- En código React: + +```jsx +const Header = () => { + return

Lista de usuarios

` +}; +``` + +Si aplicamos el mismo tipo de cambio en el resto de componentes, el fichero _index.jsx_ nos tendría que quedar así: + +```jsx +import React from "react"; +import { getUsers } from "./api"; +import "./styles.css"; + +const Header = () => { + return

Lista de usuarios

; +}; + +const User = ({ user }) => { + let randomNumber = Math.random(); + + setTimeout(() => { + randomNumber = Math.random(); + console.log(randomNumber); + }, 3000); + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; + +const List = () => { + const users = getUsers(); + return
{users.map((user) => User({ user }))}
; +}; + +export default function App() { + return ( +
+ {Header()} + {List()} +
+ ); +} +``` + +Comprobamos que nuestra aplicación renderiza la lista por la pantalla. + +**Sintaxis React** +En React vamos a poder usar la sintaxis _jsx cuando_ invocamos nuestros componentes: + +```diff +export default function App() { + return ( +
++
++ +- {Header()} +- {List()} +
+ ); +} +``` + +Además, si queremos pasar un argumento por props (argumentos de entrada a nuestro componente): + +```diff +const List = () => { + const users = getUsers(); +- return
{users.map((user) => User({ user }))}
; ++ return
{users.map((user) => )}
; +}; +``` + +Al hacer esto, la consola nos va a lanzar un error que aparece cuando renderizamos elementos iterando por una lista. Como vemos en la traza, nos pide que le pasemos al componente una key con valor único (ya veremos más adelante a que se debe): + +```diff +const List = () => { + const users = getUsers(); +- return
{users.map((user) => )}
; ++ return
{users.map((user) => )}
; +}; +``` + +Pero, como estamos viendo la variable `randomNumber` sigue estando desincronizada de nuestra interfaz de usuario. Esto se debe a que no estamos guardando ese valor en un estado, por lo que react no se entera del cambio. Para que nuestra aplicación sea reactiva hacemos el siguiente cambio: + +```diff +const User = ({ user }) => { +- let randomNumber = Math.random(); ++ const [randomNumber, setRandomNumber] = React.useState(Math.random()) + + +setTimeout(() => { +- randomNumber = Math.random(); ++ setRandomNumber(Math.random()); + console.log(randomNumber); +}, 3000); + + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; +``` + +Si nos fijamos vemos, que a pesar de que es un setTimeout (debería ejecutarse una sola vez), se está ejecutando cada tres segundos ¿Por qué? + +En el código, el setTimeout está dentro del cuerpo del componente. Eso significa que cada vez que el componente se re-ejecuta, React vuelve a crear un nuevo setTimeout. + +Cuando el setTimeout se cumple, llama a setRandomNumber, lo cual cambia el estado. Ese cambio de estado provoca un nuevo renderizado, y en ese nuevo renderizado se vuelve a crear otro setTimeout. Así entras en un bucle infinito: + +1. Ejecución/render → crea setTimeout. +2. SetTimeout → randomNumber cambia estado. +3. React detecta cambio de estado → React ejecuta componente de nuevo. +4. Vuelve al paso 1. + +La clave: no es que el setTimeout se repita automáticamente, sino que se vuelve a crear en cada ejecución. + +Cuando escribimos lógica directamente dentro de un componente de React, esa lógica se va a ejecutar en cada renderizado. Esto puede generar problemas de rendimiento, fallos en la aplicación, o incluso bucles infinitos (como en el caso de setTimeout, que se vuelve a crear en cada render). + +Para controlar cuándo y con qué condiciones se ejecuta cierto código, React nos proporciona el hook `useEffect`, que nos permite manejar efectos secundarios (side effects), como temporizadores, peticiones a APIs o suscripciones a eventos, de forma controlada. + +Su sintaxis es la siguiente: + +```jsx +useEffect(() => { + // 👇 Código (efecto) que quieres ejecutar +}, [dependencias]); +``` + +Parámetros de useEffect: + +- Callback (efecto): la función que queremos ejecutar. +- Lista de dependencias: un array que indica cuándo debe volver a ejecutarse ese callback. + +Ejemplos: + +- [] → el efecto solo se ejecuta una vez, cuando el componente se monta. +- [estado] → el efecto se ejecuta cada vez que cambia estado. +- undefined → el efecto se ejecuta en cada renderizado. (evitar) + +Así, usamos `useEffect` con un array de dependencias vacío, porque queremos que el `setTimeout` se ejecute una sola vez, cuando se crea el componente: + +```diff +const User = ({ user }) => { +const [randomNumber, setRandomNumber] = React.useState(Math.random()) + ++ React.useEffect(()=>{ +setTimeout(() => { + setRandomNumber(Math.random()); + console.log(randomNumber); +}, 3000); ++ },[]) + + return ( +
+ {user.id}: {user.name} - {randomNumber} +
+ ); +}; +``` + +Vamos a crear ahora un button que al clicar, me añada un nuevo elemento a la lista: + +```diff +const List = () => { +- const users = getUsers(); ++ Const [users, setUsers] = React.useState(getUsers()); + ++ const handleClick = () => { ++ setUsers([...users, {id: 1234, name: 'John Doe'}]) ++ } + +- return return
{users.map((user) => )}
; ++ return ( ++
++ {users.map((user) => ( ++ ++ ))} ++ ++
++ ); +}; +``` diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/README.md b/04-frameworks/01-react/02-base/01-vite-boiler/README.md index bf1aaebfc..ba0ead5f6 100644 --- a/04-frameworks/01-react/02-base/01-vite-boiler/README.md +++ b/04-frameworks/01-react/02-base/01-vite-boiler/README.md @@ -1,4 +1,4 @@ -## 02 Web Boiler plate +## 01 Vite boiler plate ## Summary @@ -17,7 +17,6 @@ Highlights: - Created a `tsconfig.json` with a minimal configuration. - Vite uses esbuild for transpilation (fast, no type checking). - Enabled `isolatedModules` and `useDefineForClassFields` for `esbuild`compatibility. -- Type checking is handled separately (via tsc or IDE). In the following example we will take this as a starting point and we will go step by step adding support for React. diff --git a/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md b/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md index f8eeb987b..f74a2d255 100644 --- a/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md +++ b/04-frameworks/01-react/02-base/01-vite-boiler/readme_es.md @@ -1,4 +1,4 @@ -## 02 Web Boiler plate +## 01 Vite boiler plate ## Resumen @@ -17,7 +17,6 @@ Puntos destacados: - Se creó un `tsconfig.json` con una configuración mínima. - Vite utiliza esbuild para la transpilación (rápido, sin comprobación de tipos). - Se habilitó `isolatedModules` y `useDefineForClassFields` para que sea compatible con `esbuild`. -- La comprobación de tipos se maneja por separado (a través de tsc o del IDE). En el siguiente ejemplo tomaremos este como punto de partida y, paso a paso, añadiremos soporte para React. diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme.md b/04-frameworks/01-react/02-base/02-vite-react/readme.md index a8b4b8812..d1e39e3f7 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme.md @@ -1,4 +1,4 @@ -# 02 Vite React +# 02 Vite boiler plate - React ## Summary @@ -7,7 +7,7 @@ This example takes the _01-vite-boiler_ example as a starting point. We will go step by step adding the necessary configuration so that we integrate **React** into our build process. -# Step by Step guide +# Step by Step - First we copy the previous example, and do a _npm install_ @@ -21,7 +21,7 @@ npm install npm install react react-dom --save ``` -- No install types for `react` y `react-dom` ad dev dependencies: +- Install types for `react` y `react-dom` ad dev dependencies: ```bash npm install @types/react @types/react-dom -D @@ -29,40 +29,40 @@ npm install @types/react @types/react-dom -D - Now open `tsconfig.json` file and set following compiler option to support `jsx` notation in our TypeScript files: - _tsconfig.json_ +_tsconfig.json_ - ```diff - "compilerOptions": { - "esModuleInterop": true, - "isolatedModules": true, - + "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], - "module": "ESNext", - ``` +```diff + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, ++ "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", +``` - ⚡ `jsx` is a JavaScript syntax extension that will allow us to write HTML-in-JS and is typically used by React components. +⚡ `jsx` is a JavaScript syntax extension that will allow us to write HTML-in-JS and is typically used by React components. - In order to make `vite` fully support `jsx` syntax (among other things) we will add a plugin, otherwise, `esbuild` won't be able to transpile our `react` source files written in `jsx` syntax: - ```bash - npm install @vitejs/plugin-react --save-dev - ``` +```bash +npm install @vitejs/plugin-react --save-dev +``` - Finally, let's modify `vite.config.ts` to add the newly installed plugin: - _vite.config.ts_ +_vite.config.ts_ - ```diff - import { defineConfig } from "vite"; - import checker from "vite-plugin-checker"; - + import react from "@vitejs/plugin-react"; +```diff + import { defineConfig } from "vite"; + import checker from "vite-plugin-checker"; ++ import react from "@vitejs/plugin-react"; - export default defineConfig({ - - plugins: [checker({ typescript: true })], - + plugins: [checker({ typescript: true }), react()], - }); + export default defineConfig({ +- plugins: [checker({ typescript: true })], ++ plugins: [checker({ typescript: true }), react()], + }); - ``` +``` - Let's create our first React component. diff --git a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md index a862f526e..12235b0c7 100644 --- a/04-frameworks/01-react/02-base/02-vite-react/readme_es.md +++ b/04-frameworks/01-react/02-base/02-vite-react/readme_es.md @@ -1,12 +1,12 @@ -# 02 Vite React +# 02 Vite boiler plate - React -## Summary +## Resumen Este ejemplo parte desde el ejemplo _01-vite-boiler_. Vamos a ir paso a paso, añadiendo la configuración necesaria para integrar **React**. -# Guía paso a paso +# Paso a paso - Antes que nada nos instalamos todos los paquetes necesarios del boiler plate ejecutando _npm install_ @@ -28,40 +28,40 @@ npm install @types/react @types/react-dom -D - Para hacer que TS entienda la notación `jsx` añadimos lo siguiente en el fichero `tsconfig.json`: - _tsconfig.json_ +_tsconfig.json_ - ```diff - "compilerOptions": { - "esModuleInterop": true, - "isolatedModules": true, - + "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], - "module": "ESNext", - ``` +```diff + "compilerOptions": { + "esModuleInterop": true, + "isolatedModules": true, ++ "jsx": "react-jsx", + "lib": ["ESNext", "DOM"], + "module": "ESNext", +``` - ⚡ `jsx` es azucar sintáctico que permite escribir HTML-in-JS. Esta sintaxis es la que vamos a usar con los componentes de React. +⚡ `jsx` es azúcar sintáctico que permite escribir HTML-in-JS. Esta sintaxis es la que vamos a usar con los componentes de React. - Para hacer que `vite` soporte la sintaxis `jsx` (y otras cosas) tenemos que añadir un plugin, sino, `esbuild` no será capaz de transpilar nuestros ficheros de `react`, escritos en formato en `jsx`: - ```bash - npm install @vitejs/plugin-react --save-dev - ``` +```bash +npm install @vitejs/plugin-react --save-dev +``` - Finalmente, modificamos `vite.config.ts` añadiendo nuestro plugin: - _vite.config.ts_ +_vite.config.ts_ - ```diff - import { defineConfig } from "vite"; - import checker from "vite-plugin-checker"; - + import react from "@vitejs/plugin-react"; +```diff + import { defineConfig } from "vite"; + import checker from "vite-plugin-checker"; ++ import react from "@vitejs/plugin-react"; - export default defineConfig({ - - plugins: [checker({ typescript: true })], - + plugins: [checker({ typescript: true }), react()], - }); + export default defineConfig({ +- plugins: [checker({ typescript: true })], ++ plugins: [checker({ typescript: true }), react()], + }); - ``` +``` - Creemos ahora nuestro primer componente @@ -75,7 +75,7 @@ export const App = () => { }; ``` -Actualizamos*./src/index.ts* a _./src/index.tsx_. Ajustamos la extensión también en el fichero _./index.html_. +Actualizamos _./src/index.ts_ a _./src/index.tsx_. Ajustamos la extensión también en el fichero _./index.html_. - Vamos a usar el componente que acabamos de crear. Para poder integrar ese componente (y el resto de la aplicación) en nuestro html, hacemos uso de _createRoot_. diff --git a/04-frameworks/01-react/02-base/03-list-users/readme.md b/04-frameworks/01-react/02-base/03-list-users/readme.md index e92e50dd7..d75d8f4e6 100644 --- a/04-frameworks/01-react/02-base/03-list-users/readme.md +++ b/04-frameworks/01-react/02-base/03-list-users/readme.md @@ -1,4 +1,4 @@ -# 04 List Users +# 03 List Users ## Summary @@ -115,12 +115,9 @@ export const App = () => { With these lines of code, we are iterating through the array of members and creating a span element for each entry, to take into account: -- key: when we create elements dynamically, we need to add a unique key to them (so React can optimise the rendering). - the rendering). - +- key: when we create elements dynamically, we need to add a unique key to them (so React can optimize the rendering). - Member Login: we read the value of the current array element and display the login field. - -- Now that we see that it works we are going to fit this in a grid, let's define some gobal styles +- Now that we see that it works we are going to fit this in a grid, let's define some global styles (check [CSS modules example](https://github.com/Lemoncode/master-frontend-lemoncode/tree/master/03-bundling/01-webpack/12-css-modules), to learn how to configure component isolated CSS) _./src/styles.css_ diff --git a/04-frameworks/01-react/02-base/03-list-users/readme_es.md b/04-frameworks/01-react/02-base/03-list-users/readme_es.md index b62d9d1ef..3ae5f94d9 100644 --- a/04-frameworks/01-react/02-base/03-list-users/readme_es.md +++ b/04-frameworks/01-react/02-base/03-list-users/readme_es.md @@ -1,4 +1,4 @@ -# 04 List Users +# 03 List Users ## Resumen @@ -14,7 +14,7 @@ con TypeScript y como hacer nuestro código más mantenible. Que vamos a aprender en este ejemplo: - Cómo crear un componente de visualización sin tener que depender de leer - de una fuenta remota. + de una fuente remota. - Cómo iterar y mostrar una lista de resultados. - Cómo hacer una llámada asícnrona para pedir datos a una api remota. - Cómo meter estos datos en el estado de nuestro componente en React. @@ -36,7 +36,7 @@ npm install https://api.github.com/orgs/lemoncode/members ``` -- Vamos a crear un set de datos parecido que mueste dos miembros de una organización. +- Vamos a crear un set de datos parecido que muestre dos miembros de una organización. _./src/app.tsx_ @@ -125,7 +125,7 @@ a tener en cuenta: - Ahora que vemos que funciona vamos a encajar esto en un tabla: -- Ahora que vemos que funciona vamos a encajar esto en un _grid_, vamos a definir algunos estilos gobales +- Ahora que vemos que funciona vamos a encajar esto en un _grid_, vamos a definir algunos estilos globales (revisa [Ejemplo de módulos CSS](https://github.com/Lemoncode/master-frontend-lemoncode/tree/master/03-bundling/01-webpack/12-css-modules), para aprender a configurar el CSS aislado de los componentes). _./src/styles.css_ @@ -199,7 +199,7 @@ export const App = () => { Así que hemos creado aquí un contenedor CSS Grid añadimos la cabecera y un bucle de todos los elementos de la lista de usuarios. - Hasta aquí muy bien pero... yo quiero tirar de la API de Github no de datos mockeados, vamos a empezar - por eliminar los datos mock e inicializar el estado de nuestro componente a un array vacio: + por eliminar los datos mock e inicializar el estado de nuestro componente a un array vacío: ```diff - const membersMock = [ @@ -220,7 +220,7 @@ export const App = () => { + const [members, setMembers] = React.useState([]); ``` -- ¿Cómo puedo hacer la llamada al servidor de Github y traerme los datos justo cuando el compomenten se monte en mi HTML? +- ¿Cómo puedo hacer la llamada al servidor de Github y traerme los datos justo cuando el componente se monte en mi HTML? Para ello vamos a usar _useEffect_ esto lo veremos más adelante cuando cubramos la parte de hooks _./src/app.tsx_ @@ -236,7 +236,7 @@ export const App = () => { ``` Aquí ejecutamos un código justo cuando el componente se monta el DOM, los corchetes que nos encontramos al final de useEffect -son los que indican que sólo se ejecute una sóla vez al montarse el componente, aprenderemos como funciona esto en detalle más adelante. +son los que indican que sólo se ejecute una sola vez al montarse el componente, aprenderemos como funciona esto en detalle más adelante. - Ahora nos queda realizar la llamada AJAX dentro de ese _useEffect_ @@ -252,7 +252,7 @@ _./src/app.tsx_ Más adelante veremos que React 19 ya trae un hook específico para esto. -¿Qué estamos haciendo aquí? Estamos haciendo una llamada a la API REST de Github, esta api es asíncrona (de ahí que utlicemos +¿Qué estamos haciendo aquí? Estamos haciendo una llamada a la API REST de Github, esta api es asíncrona (de ahí que utilicemos promesas), primero parseamos el resultado a _json_ y después asignamos ese resultado al estado de nuestro componente invocando a _setMembers_ diff --git a/04-frameworks/01-react/02-base/04-list-refactor/readme.md b/04-frameworks/01-react/02-base/04-list-refactor/readme.md index 25f0b621b..cb2758631 100644 --- a/04-frameworks/01-react/02-base/04-list-refactor/readme.md +++ b/04-frameworks/01-react/02-base/04-list-refactor/readme.md @@ -1,10 +1,10 @@ -# 05 List Refactor +# 04 List Refactor ## Summary This example takes the _03-list-users_ example as a starting point. -We will add some refactor to enhance project readiblity and maintalibility. +We will add some refactor to enhance project readability and maintainability. ## Step by step guided example @@ -119,7 +119,7 @@ import { MemberEntity } from './model'; ``` > We could even create a subcomponent for the table headers if we wanted to, -> this will be an excercise to do in a next example. +> this will be an exercise to do in a next example. - One last step, the _App_ component still has too much code, it should just instantiate the main component and that's it. the main component and that's it, let's simplify this. @@ -193,5 +193,4 @@ export const App = () => { }; ``` -Can we continue to clean up this code and build something that is maintainable and scalable in the future? The answer is yes, we will see -we'll see later on. +Can we continue to clean up this code and build something that is maintainable and scalable in the future? The answer is yes, we'll see later on. diff --git a/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md b/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md index 586015158..09f9382ce 100644 --- a/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md +++ b/04-frameworks/01-react/02-base/04-list-refactor/readme_es.md @@ -1,4 +1,4 @@ -# 05 List Refactor +# 04 List Refactor ## Resumen @@ -14,7 +14,7 @@ npm install - Antes de seguir vamos a arreglar un pequeño bug que dejamos en el ejemplo anterior, se nos olvido poner la key en el map don de generamos dinámicamente - la files con los miembros que pertenecen a una organizacion. + la files con los miembros que pertenecen a una organización. _./src/app.tsx_ @@ -59,8 +59,8 @@ export const App = () => { - Ahora si cometemos una equivocación al escribir uno de los campos en nuestro componente fila, el IDE nos lo marcará en rojo. -- La siguiente mejora que vamos a introducir tiene que ver con el JSX que genramos, - fijate que apenas hemos metido una tabla y ya nos cuesta seguirlo, ¿No podríamos +- La siguiente mejora que vamos a introducir tiene que ver con el JSX que generamos, + fíjate que apenas hemos metido una tabla y ya nos cuesta seguirlo, ¿No podríamos simplificar esto? La respuesta si, podemos extraer la parte que pinta un miembro en la tabla a un componente, esto lo podemos dejar en el mismo fichero o sacarlo a un fichero aparte, vamos a ello: @@ -88,7 +88,7 @@ export const MemberTableRow: React.FC = (props) => { }; ``` -Fijate que interesante como un componente se queda como una caja negra que expone su interacción con +Fíjate que interesante como un componente se queda como una caja negra que expone su interacción con el exterior vía propiedades. - Ahora podemos sustituirlo en App: diff --git a/04-frameworks/01-react/02-base/05-list-excercise/readme_en.md b/04-frameworks/01-react/02-base/05-list-excercise/readme.md similarity index 87% rename from 04-frameworks/01-react/02-base/05-list-excercise/readme_en.md rename to 04-frameworks/01-react/02-base/05-list-excercise/readme.md index c12899bb4..17e2e52ca 100644 --- a/04-frameworks/01-react/02-base/05-list-excercise/readme_en.md +++ b/04-frameworks/01-react/02-base/05-list-excercise/readme.md @@ -1,6 +1,6 @@ # Summary -Now is your turn to get your hands wet coding some use stories :) +Now is your turn to get your hands wet coding with some challenges :) # Challenges diff --git a/04-frameworks/01-react/02-base/05-list-excercise/readme_es.md b/04-frameworks/01-react/02-base/05-list-excercise/readme_es.md index 5f38fafcb..ec30268fa 100644 --- a/04-frameworks/01-react/02-base/05-list-excercise/readme_es.md +++ b/04-frameworks/01-react/02-base/05-list-excercise/readme_es.md @@ -1,6 +1,6 @@ # Resumen -Ahora es tu turno de mojarte las manos codificando :) +Ahora es tu turno de mojarte las manos con algunos desafíos :) # Desafíos @@ -23,5 +23,5 @@ Pistas ¿ Qué tienes que tocar? 1. Actualiza el modelo y añade el campo de perfil 2. Actualiza el componente member-table-row, añade una columna más -3. En esa columna muestra el nuevo campo y metelo +3. En esa columna muestra el nuevo campo y mételo dentro de un anchor (un enlace de html) diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md index bf1aaebfc..71dd58bbf 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md @@ -17,7 +17,6 @@ Highlights: - Created a `tsconfig.json` with a minimal configuration. - Vite uses esbuild for transpilation (fast, no type checking). - Enabled `isolatedModules` and `useDefineForClassFields` for `esbuild`compatibility. -- Type checking is handled separately (via tsc or IDE). In the following example we will take this as a starting point and we will go step by step adding support for React. diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md index f8eeb987b..623080ef1 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md @@ -17,7 +17,6 @@ Puntos destacados: - Se creó un `tsconfig.json` con una configuración mínima. - Vite utiliza esbuild para la transpilación (rápido, sin comprobación de tipos). - Se habilitó `isolatedModules` y `useDefineForClassFields` para que sea compatible con `esbuild`. -- La comprobación de tipos se maneja por separado (a través de tsc o del IDE). En el siguiente ejemplo tomaremos este como punto de partida y, paso a paso, añadiremos soporte para React. From 182ea891daaf5b6e617707d203d82cb55c99773f Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 16:44:45 +0200 Subject: [PATCH 29/31] review react hooks - use-state --- .../03-react-hooks/00-boilerplate/Readme.md | 26 +++++++------------ .../00-boilerplate/Readme_es.md | 22 ++++++---------- .../03-react-hooks/01-use-state/Readme.md | 6 ++--- .../03-react-hooks/01-use-state/Readme_es.md | 16 ++++++------ .../03-react-hooks/01-use-state/index.html | 2 +- .../02-use-state-object/Readme.md | 11 ++++---- .../02-use-state-object/Readme_es.md | 4 +-- .../02-use-state-object/index.html | 2 +- 8 files changed, 38 insertions(+), 51 deletions(-) diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md index 71dd58bbf..441e05ada 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme.md @@ -1,22 +1,16 @@ -## 02 Web Boiler plate +# 02 Vite boiler plate - React ## Summary -In this example there is a vite boiler plate set up with Typescript support, just in the step before -to adding React support. +Boiler plate extracted from _02-base/02-vite-react_. -It is based on the Vite examples. +Below, main points. For more info, check the original repo or the Vite module. -This example is the only one that doesn't have a step-by-step (if you need guidance, you can go to the -vite examples you'll find in this repository). - -Highlights: - -- Added TypeScript as a local dev dependency. -- Switched project to use ES Modules in package.json. -- Created a `tsconfig.json` with a minimal configuration. +- Installation of `typeScript` as a local development dependency. +- Installation of `@vitejs/plugin-react` as a local development dependency (support for `jsx` and `tsx`). +- Installation of `react` and `react-dom` as dependencies. +- Installation of the types `@types/react` and `@types/react-dom` as local development dependencies. +- The project was changed to use ES Modules `package.json`. +- A `tsconfig.json` was created with a minimal configuration, prepared to support `jsx` format. - Vite uses esbuild for transpilation (fast, no type checking). -- Enabled `isolatedModules` and `useDefineForClassFields` for `esbuild`compatibility. - -In the following example we will take this as a starting point and we will go step by step adding -support for React. +- `isolatedModules` and `useDefineForClassFields` were enabled to be compatible with `esbuild`. diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md index 623080ef1..f206cfeee 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/Readme_es.md @@ -1,22 +1,16 @@ -## 02 Web Boiler plate +# 02 Vite boiler plate - React ## Resumen -En este ejemplo desarrollamos un boilerplate de Vite configurado con soporte para TypeScript, justo en el paso previo -a añadir soporte para React. +Boiler plate extraído de _02-base/02-vite-react_. -Está basado en los ejemplos de Vite. +A continuación, puntos principales. Para más info, acudir a repo original o módulo de vite. -Este ejemplo es el único que no tiene una guía paso a paso (si necesitas orientación, puedes consultar los -ejemplos de Vite que encontrarás en este repositorio). - -Puntos destacados: - -- Se agregó TypeScript como dependencia de desarrollo local. +- Instalación de `typeScript` como dependencia de desarrollo local. +- Instalación de `@vitejs/plugin-react` como dependencia de desarrollo local (soporte `jsx` y `tsx`) +- Instalación de `react` y `react-dom` como dependencias. +- Instalación de los tipos de `@types/react` y `@types/react-dom` como dependencia de desarrollo local. - Se cambió el proyecto para usar ES Modules `package.json`. -- Se creó un `tsconfig.json` con una configuración mínima. +- Se creó un `tsconfig.json` con una configuración mínima, preparada para soportar formato `jsx`. - Vite utiliza esbuild para la transpilación (rápido, sin comprobación de tipos). - Se habilitó `isolatedModules` y `useDefineForClassFields` para que sea compatible con `esbuild`. - -En el siguiente ejemplo tomaremos este como punto de partida y, paso a paso, añadiremos -soporte para React. diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md index 96b95eb8e..a158f1868 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md @@ -67,8 +67,8 @@ If you come to a React project and you come across code like this, it's a bad sm of the variable _myName_ will always be _John Doe_. Why? the component is just function that is executed over and over on each repaint. -- If we asign a value directly to the _input_ we are skipping two - main pillars of React: unidirection flow and asynchronous state assignment. +- If we assign a value directly to the _input_ we are skipping two + main pillars of React: unidirectional flow and asynchronous state assignment. If you want to see it in action (input not working) you just have to add it to the _app.tsx_ file. @@ -86,7 +86,7 @@ export const App = () => { Ok... How can I handle this? Using React hooks! Let's take a look to _React.useState_, this hook: -- Is initialized with a default value. +- Optionally, it can be initialized to a given value. - It returns an array that contains a getter and a setter (it allows you to access the value that is in useState and allows you diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme_es.md b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme_es.md index b7f71a042..5aa6263e4 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme_es.md @@ -27,7 +27,7 @@ _demo.tsx_ import React from "react"; ``` -Añadimos al fichero un componente de tipo funcion: +Añadimos al fichero un componente de tipo función: _demo.tsx_ @@ -38,15 +38,15 @@ export const MyComponent: React.FC = () => { ``` - Usando la palabra reservada _export_ podemos exponer este fichero al exterior. -- No es extrictamente necesario tiparlo con _React.FC_ (Function Component), pero +- No es estrictamente necesario tiparlo con _React.FC_ (Function Component), pero es buena idea, todo lo que nos atemos a _Typescript_ nos servirá para tener menos dolores de cabeza en el futuro. - El componente no es más que una función que devuelve elementos de React. - Fijate que en este caso no hemos puesto _Props_ ya que no consume ninguna + Fíjate que en este caso no hemos puesto _Props_ ya que no consume ninguna del exterior. - Vamos a por la parte interesante, seguro que nuestra mente Java o Angular - nos mueve a implementar lo siguiente (**IMPORTANTE: ESTO ESTA MAL**). + nos mueve a implementar lo siguiente (**IMPORTANTE: ESTO ESTÁ MAL**). ```diff export const MyComponent : React.FC = () => { @@ -65,7 +65,7 @@ export const MyComponent : React.FC = () => { ``` Si llegáis a un proyecto React y os encontráis código como este, huele a que los -que lo han codificado no se tomaron el tiempo de aprender las bases de esta +que lo han codificado no se tomaron el tiempo de aprender las bases de estas librerías, veamos por qué: - Al crear una variable, cada vez que se vuelva a repintar el componente @@ -93,13 +93,13 @@ export const App = () => { Vale... ¿Cómo puedo manejar esto? ¡Con los hooks de React! Tenemos _React.useState_. -- Se inicializa con un valor por defecto. +- Opcionalmente, se puede inicializar con un valor determinado. - Te devuelve un array que contiene una especie getter y un setter (te permite acceder al valor que está en useState y te permite hacer una petición y setearlo de forma asíncrona). -- La manera más cómoda de consumir lo que devuevel ese _useState_ es hacer +- La manera más cómoda de consumir lo que devuelve ese _useState_ es hacer destructuring sabiendo que el primer elemento del array siempre será nuestro _getter_ y el segundo nuestro \_setter. @@ -156,7 +156,7 @@ setear el estado de _myName_. - Cuando se ejecute el código del componente y llegue a la línea de código que hace el _useState_, en vez de _John Doe_ se le facilitará el nombre que se almaceno con _setState_ -- Al repintar el componente se usará ese nuevo valor mostrandolo +- Al repintar el componente se usará ese nuevo valor mostrándolo por pantalla. Es un cambio de mentalidad grande,... intenta repetir este ejemplo diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/index.html b/04-frameworks/01-react/03-react-hooks/01-use-state/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/index.html +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md index 5b19a0fb3..0d141f6e8 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md @@ -17,7 +17,7 @@ add an update on a given object, we create a new one). npm install ``` -- Let's go store in the state an object that has the name +- Let's store in the state an object that has the name and last name of a given user. We can write something like: _./src/demo.tsx_ @@ -72,7 +72,7 @@ If we start the application we can see how the name and lastname are displayed.

{userInfo.name} {userInfo.lastname}

-- setMyName(e.target.value)} /> +- setMyName(e.target.value)} /> + userInfo.name = e.target.value} @@ -82,8 +82,8 @@ If we start the application we can see how the name and lastname are displayed. ``` This is not going to work, we are again applying a Java / Angular approach, -we are trying to modify something that is alive only when the function is being -executed, once the component is rerended this value will be lost. +we are trying to modify something that is alive only while the function is being +executed, once the component is rerended this value is be lost. - The way to do this is by creating a new object and assigning it using the _setState_ method. In order to do this copy we use the spread operator (by doing this, all the fields @@ -143,8 +143,7 @@ entry for the one that had changes. ); ``` -Now we can test and see that we can update both the name and -lastname. +Now we can test and see that we can update both the name and lastname. # About Basefactor + Lemoncode diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme_es.md b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme_es.md index 54880742e..d3d5c39ed 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme_es.md @@ -34,7 +34,7 @@ export const MyComponent: React.FC = () => { Así creamos un estado al que le almacenamos el objeto, pero nos vendría bien tener algo de strong typing que nos ayude a encontrar fallos tontos -del tipo _me olvide poner la "t" en lastname_. +del tipo _me olvidé poner la "t" en lastname_. ```diff + interface UserInfo { @@ -66,7 +66,7 @@ export const MyComponent: React.FC = () => { - Si arrancamos la aplicación podemos ver cómo se muestra el nombre y apellido. - Ahora vamos al turrón, podríamos estar tentados de modificar directamente userInfo y - ver qué pasa, hacer algo así como (**SPOILER ALERT: ESTO ESTA MAL**): + ver qué pasa, hacer algo así como (**SPOILER ALERT: ESTO ESTÁ MAL**): ```diff return ( diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html b/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks From 9af9f5afab3bf03abd2a6c0bde33c4bf0a9ff75b Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 18:51:03 +0200 Subject: [PATCH 30/31] react hooks 1 --- .../03-react-hooks/00-boilerplate/index.html | 2 +- .../03-react-hooks/01-use-state/Readme.md | 2 +- .../02-use-state-object/Readme.md | 2 +- .../03-component-mount/Readme.md | 29 +++++++------- .../03-component-mount/index.html | 2 +- .../03-component-mount/readme_es.md | 39 ++++++++++--------- .../04-component-unmount/Readme.md | 20 +++++----- .../04-component-unmount/Readme_es.md | 12 +++--- .../04-component-unmount/index.html | 2 +- .../05-component-update-render/Readme.md | 9 ++--- .../05-component-update-render/Readme_es.md | 10 ++--- .../05-component-update-render/index.html | 2 +- 12 files changed, 63 insertions(+), 68 deletions(-) diff --git a/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md index a158f1868..5b7c901c5 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md @@ -1,6 +1,6 @@ # 01 Use State -## Resume +## Summary This example takes the _00-boiler-plate_ example as a starting point. diff --git a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md index 0d141f6e8..6fc56879c 100644 --- a/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md @@ -1,6 +1,6 @@ # 02 Use State Object -## Resume +## Summary This example takes the _01-use-state_ as a starting point. diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md b/04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md index d4824f6b0..3ccf0b864 100644 --- a/04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/Readme.md @@ -1,30 +1,30 @@ # 03 Component Did Mount -## Resume +## Summary This example takes as a starting point the _02-use-state-object_ example. Let's start practicing with another React's core hook: _useEffect_ This Hook allows us to subscribe on certain events (check when the -component is mounted, check when the component is unmounted, on +component is mounted, when the component is unmounted, on every render, or when a given property is updated). -Let's start with the most basic, execute a given code when a +Let's start with the most basic: execute a given code when a component is mounted in the DOM. -A common scenario: you want to run some code when a component it's loaded into +A common scenario: running some code when a component it's loaded into the DOM, for example loading a list of clients when the component is mounted. There can be scenarios when we need some code to be executed when a given property value changes or right after each render. -There may be scenarios when all this operations are not synchronous? For instance I want making a call to a server rest api, -this will return a promise, it is not safe at all to run this directly in a functional component -since the functional component is executed and destroyed, to manage these side effects) we can make use of +What if these operations are not synchronous? For instance making a call to a server rest api will return a promise, +so it is not safe at all to run this directly in a functional component, +since the functional component is executed and destroyed (to manage these side effects) we can make use of _React.useEffect_ -In this example we are going to simulate a call to a rest api, in order to retrieve a name (we will use +In this example we are going to simulate a request to a rest api, in order to retrieve a name (we will use _setTimeout_). ## Steps @@ -54,13 +54,13 @@ export const MyComponent = () => { }; ``` -- If we run the example, the name field will be empty, but we want +- If we run the example, the name field will be empty, but how to assign some value right when the component is mounted? We can make use of - _React.useEffect_ passing as a second argument an empty array (that's important + _React.useEffect_, passing as a second argument an empty array (that's important if we don't pass this the code inside the _useEffect_ would be executed on mount and after every render). -_./src/demo.js_ +_./src/demo.tsx_ ```diff import React from "react"; @@ -86,7 +86,7 @@ export const MyComponent = () => { * Let's go one step further, let's simulate an asynchronous call (we will do it using _setTimeout_). -_./src/demo.js_ +_./src/demo.tsx_ ```diff import React from "react"; @@ -111,8 +111,9 @@ export const MyComponent = () => { }; ``` -- Now _John_ is displayed after 1,5 seconds, instead of _setTimeout_ you could - use here _fetch_ or any other similar approach to make an ajax request. +Now _John_ is displayed after 1,5 seconds. +As a next step, instead of a _setTimeout_ you could +use here _fetch_ or any other similar approach to make an ajax request. # About Basefactor + Lemoncode diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html b/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md b/04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md index ea72abb86..603f93316 100644 --- a/04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/readme_es.md @@ -19,9 +19,10 @@ ejemplo cargar una ficha de un cliente de una API REST de servidor. También hay operaciones que queremos poder ejecutar cuando cambie un valor, o en después de cada render. -¿Qué pasa si esas operaciones no son síncronas? Por ejemplo quiero -tirar de un setTimeout o hacer un llamada a un servidor, esto devolvera una promesa, no es nada seguro ejecutar esto directamente en un componente funcional -ya que este se ejecuta y destruye, para esto (gestionar side effects) tenemos +¿Qué pasa si esas operaciones no son síncronas? Por ejemplo si quiero +tirar de un setTimeout o hacer un llamada a un servidor, esto devolverá una promesa. +No es nada seguro ejecutar esto directamente en un componente funcional +ya que este se ejecuta y destruye; para esto (gestionar side effects) tenemos _React.useEffect_ En este ejemplo vamos a ver como cambiar un nombre, justo cuando se @@ -36,7 +37,7 @@ utilizando _setTimeout_. npm install ``` -- Vamos a sobreescribir el fichero _demo.tsx_ con el siguiente código: +- Vamos a sobrescribir el fichero _demo.tsx_ con el siguiente código: ```tsx import React from "react"; @@ -64,7 +65,7 @@ npm start - Vemos que el campo nombre está en blanco, esto es normal ya que le hemos asignado el valor inicialización a cade en blanco. -- ¿Y si quisieramos asignar un valor justo cuando se monta el componente +- ¿Y si quisiéramos asignar un valor justo cuando se monta el componente en el dom? Podemos hacer uso de _React.useEffect_ ```diff @@ -80,7 +81,7 @@ export const MyComponent = () => { Al ejecutar esto podemos ver como aparece el nombre de _John_ por pantalla. -Si depuramos podemos y ponemos un breakpoint justo donde se invoca +Si depuramos y ponemos un breakpoint justo donde se invoca a _react.useState_, otro en el render y otro dentro del código de _useEffect_ podemos ver que se llaman en el siguiente orden: - Primero el _useState_ @@ -94,16 +95,16 @@ a ejecutar el código… **React.useEffect** -En su primer parametro un código que puede contener sideffects +En su primer parámetro un código que puede contener sideffects (una llamada a servidor, un setTimeout...). -Si no le informamos más parametros, esta función se ejecutara siempre -despues de cada render. +Si no le informamos más parámetros, esta función se ejecutará siempre +después de cada render. Esto no está mal, pero mucha veces nos hace falta acotar la ejecución -de cierto código (ejecutate sólo después del primer render del componente, -ejecutate sólo antes ciertas condiciones), por ejemplo podríamos decirle -al código que se ejecutará sólo cuando cambiará la propiedad _username_ +de cierto código (ejecútate sólo después del primer render del componente, +ejecútate sólo antes ciertas condiciones), por ejemplo podríamos decirle +al código que se ejecutará sólo cuando cambie la propiedad _username_ ```tsx React.useEffect(() => { @@ -112,24 +113,24 @@ React.useEffect(() => { ``` Este ejemplo sería un poco tonto porque estamos modificando _username_ dentro -del propio _useEffect_ se metería en un bucle infinito. +del propio \_useEffect, por lo que se metería en un bucle infinito. Un tema interesante: -- Hemos visto que si no informamos el segundo parametro no para de ejecutarse - despues de cada render. +- Hemos visto que si no informamos el segundo parámetro no para de ejecutarse + después de cada render. -- También que si informamos una lista de valores como segundo parametro +- También que si informamos una lista de valores como segundo parámetro se ejecuta cuando estos valores cambian. Peeero ¿Y si informamos esa lista como vacía? Si hacemos esto, el código dentro del useEffect se ejecutará la primera vez (después del primer renderizado) -y no volvera a ejecutarse más ya que le estamos diciendo que no depende de ningún -valor de las propiedades o del estado, de esta manera no volverás a ejecutarse +y no volverá a ejecutarse más ya que le estamos diciendo que no depende de ningún +valor de las propiedades o del estado, de esta manera no volverá a ejecutarse (Para los que ya hayáis trabajado antes con React esto se parece al componentDidMount de los componentes de clase de React). -Para cerrar este ejemplo vamos a simular una llamada asíncrono utilizando +Para cerrar este ejemplo vamos a simular una llamada asíncrona utilizando _setTimeout_ ```diff diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md index 4ff9123bb..efa2dbc8e 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme.md @@ -1,8 +1,8 @@ # 04 Component unmount -## Resume +## Summary -This example takes the _03-component-mount_ example as starting point. +This example takes the _03-component-mount_ example as a starting point. In this example we are going to see how to free resources when we unmount a DOM component. @@ -16,9 +16,9 @@ npm install - We are going to create a component that shows or hides a text depending on a boolean flag. -Overwrite _demo.js_ file with the following content. +Overwrite _demo.tsx_ file with the following content. -_./src/demo.js_ +_./src/demo.tsx_ ```jsx import React from "react"; @@ -76,10 +76,10 @@ export const MyComponent = () => { }; ``` -- Now we got a childr component that is mounted / unmounted from the dom when a user clicks on a button. +- Now we got a child component that is mounted / unmounted from the DOM when an user clicks on a button. -How could we do to display a message on the console -browser when the child component will be mounted? +How could display a message in the browser console +when the child component is mounted? If we remember the previous example, we can use _React.useEffect_. Before continue just give a try by yourself. @@ -97,10 +97,10 @@ export const MyChildComponent = () => { }; ``` -- Now comes the interesting part, what if we want to show a message on the browser console when the component is unmounted from the DOM? Just +- Now it comes the interesting part, what if we want to show a message in the browser console when the component is unmounted from the DOM? Just by adding in the return value of that _useEffect_ a function that will be called when the component is unmounted. -_./src/demo.js_ +_./src/demo.tsx_ ```diff export const MyChildComponent = () => { @@ -110,7 +110,7 @@ export const MyChildComponent = () => { }, []); ``` -Any useful scenarios? Imagine that you open a connection to a websocket and you want to close it when the user hides the component, how do you free resources in a proper way? By using this approach. +Any useful scenarios? Imagine you open a connection to a websocket and you want to close it when the component is unmounted, how do you free resources in a proper way? By using this approach. # About Basefactor + Lemoncode diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md index de91a6c03..f02b5d6c3 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/Readme_es.md @@ -71,12 +71,12 @@ export const MyComponent = () => { }; ``` -- Ahora tenemos un componente hijo que pinchando en un botón +- Ahora tenemos un componente hijo que clicando en un botón se monta o desmonta del dom. ¿Cómo podríamos hacer para mostrar un mensaje por la consola del navegador cuando se montara el componente hijo? -Si recordamos el ejemplo anterior,sería con _React.useEffect_ +Si recordamos el ejemplo anterior, sería con _React.useEffect_ ¿Te animas a intentarlo? Dale a la pausa al video y ponte :). Podríamos hacer algo así como: @@ -93,9 +93,9 @@ export const MyChildComponent = () => { }; ``` -- Ahora viene la parte interesante, y si queremos mostrar un mensaje - por la console del navegador cuando el componente se desmonta del DOM? - En la misma función que ponemos como primer parametro devolvemos +- Ahora viene la parte interesante, ¿Y si queremos mostrar un mensaje + por la consola del navegador cuando el componente se desmonta del DOM? + En la misma función que ponemos como primer parámetro devolvemos la función de "limpieza"... _useEffect_ se va a guardar esa función hasta que desmonte el DOM para invocarla: @@ -107,7 +107,7 @@ export const MyChildComponent = () => { }, []); ``` -¿Para que me puede servir esto? Imaginate que abres una conexión a un websocket +¿Para que me puede servir esto? Imagínate que abres una conexión a un websocket y quieres cerrarla cuando el usuario oculte el componente, ¿ cómo liberas recursos de forma ordenada? Aquí lo tienes. diff --git a/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html b/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md index 2540f5ac7..d2c485828 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md @@ -1,6 +1,6 @@ # 05 Component update render -## Resume +## Summary We will take as starting point sample \_04-component-unmount. @@ -59,12 +59,12 @@ const MyChildComponent = () => { }; ``` -- Now comes the interesting part: by calling _React.useEffect_ without a second +- Now it comes the interesting part: by calling _React.useEffect_ without a second parameter, the code inside _useEffect_ will be triggered right when the component is just mounted and on any update (clean up function will be called right before the effect is triggered again). -_./src/demo.js_ +_./src/demo.tsx_ ```diff const MyChildComponent = () => { @@ -95,9 +95,6 @@ React.useEffect(() => { }); ``` -- If we start the project and open the browser console we can check the - expected behavior. - # About Basefactor + Lemoncode We are an innovating team of Javascript experts, passionate about turning your ideas into robust products. diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md index 3b0ca39e3..53a9c1dfe 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme_es.md @@ -15,7 +15,7 @@ un código justo después de cada renderizado. npm install ``` -- Vamos abrir el fichero _demo.js_ y crear el ejemplo de un componente +- Vamos abrir el fichero _demo.tsx_ y crear el ejemplo de un componente padre y un hijo que se muestra dependiendo de una condición booleana. ```tsx @@ -59,7 +59,7 @@ const MyChildComponent = () => { ``` - Ahora viene la parte interesante, vamos a llamar a _React.useEffect_ sólo - informando el primer parametro. + informando el primer parámetro. ```diff const MyChildComponent = () => { @@ -78,7 +78,7 @@ const MyChildComponent = () => { - Si ejecutamos podemos ver que este código se ejecuta después de cada renderizado del componente. -- También podemos añadir una función para liberar recursos justo antes de que se ejecute el siguiente render. +- También podemos añadir una función de limpieza (clean-up function) para liberar recursos justo antes de que se ejecute el siguiente render. ```diff React.useEffect(() => { @@ -142,10 +142,6 @@ const MyChildComponent = () => { + }, [userInfo.lastname]); ``` -```bash -npm start -``` - # ¿Te apuntas a nuestro máster? Si te ha gustado este ejemplo y tienes ganas de aprender Front End diff --git a/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html b/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks From 24439ed30ba6dfaaf9d50be1aa1fbc81b513a38c Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 18:52:04 +0200 Subject: [PATCH 31/31] grammar corrections --- .../03-react-hooks/06-ajax-field-change/Readme.md | 4 ++-- .../03-react-hooks/06-ajax-field-change/Readme_es.md | 2 +- .../03-react-hooks/06-ajax-field-change/index.html | 2 +- .../01-react/03-react-hooks/07-custom-hook/Readme.md | 12 ++++++------ .../03-react-hooks/07-custom-hook/index.html | 2 +- .../03-react-hooks/08-pure-component/Readme_es.md | 2 +- .../03-react-hooks/08-pure-component/index.html | 2 +- .../09-pure-component-callback/index.html | 2 +- .../01-react/03-react-hooks/10-use-reducer/Readme.md | 2 +- .../03-react-hooks/10-use-reducer/index.html | 2 +- .../01-react/03-react-hooks/11-use-context/Readme.md | 2 +- .../03-react-hooks/11-use-context/index.html | 2 +- .../03-react-hooks/12-set-state-func/Readme.md | 2 +- .../03-react-hooks/12-set-state-func/index.html | 2 +- .../03-react-hooks/13-async-closure/index.html | 2 +- .../03-react-hooks/14-use-ref-dom/Readme_es.md | 2 +- .../03-react-hooks/14-use-ref-dom/index.html | 2 +- .../03-react-hooks/15-memo-predicate/index.html | 2 +- .../03-react-hooks/16-use-debug-value/index.html | 2 +- .../03-react-hooks/17-why-did-you-update/index.html | 2 +- .../01-react/03-react-hooks/18-use-promise/Readme.md | 4 ++-- .../03-react-hooks/18-use-promise/index.html | 2 +- .../99-promise-unmounted-R17/Readme.md | 4 ++-- .../99-promise-unmounted-R17/Readme_es.md | 4 ++-- .../99-promise-unmounted-R17/index.html | 2 +- 25 files changed, 34 insertions(+), 34 deletions(-) diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme.md b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme.md index b7789b8e5..27078f513 100644 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme.md @@ -1,6 +1,6 @@ # 06 Ajax field change -## Resume +## Summary This example takes as a starting point the example \ \_05-component-update-render. @@ -16,7 +16,7 @@ As a bonus, we will check how to use Debounce (wait a little until the user stop npm install ``` -- Let's open the _demo.js_, and let's add an entry in the state that stores the current search filter, and another state in which we +- Let's open the _demo.tsx_, and let's add an entry in the state that stores the current search filter, and another state in which we are going to store a list of users. _./src/demo.tsx_ diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme_es.md b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme_es.md index 6e0d253f3..4fecef354 100644 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/Readme_es.md @@ -21,7 +21,7 @@ así llamadas innecesarias). npm install ``` -- Vamos abrir el fichero _demo.js_ y vamos añadir una entrada en el +- Vamos abrir el fichero _demo.tsx_ y vamos añadir una entrada en el estado que almacene el filtro actual de busqueda, y otra en la que almacene una lista de usuarios. diff --git a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html +++ b/04-frameworks/01-react/03-react-hooks/06-ajax-field-change/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/Readme.md b/04-frameworks/01-react/03-react-hooks/07-custom-hook/Readme.md index b7cc0439c..ac3763b4f 100644 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/Readme.md @@ -1,8 +1,8 @@ # 07 Custom hooks -## Resume +## Summary -This example takes as its starting point the \ _06-ajax-field-change example. +This example takes as its starting point the \ \_06-ajax-field-change example. Hooks are cool, but our functional component seems to get cluttered, is there a way to extract functionality outside the functional component? @@ -31,13 +31,13 @@ export const MyComponent = () => { // Load full list when the component gets mounted and filter gets updated React.useEffect(() => { fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) - .then(response => response.json()) - .then(json => setUserCollection(json)); + .then((response) => response.json()) + .then((json) => setUserCollection(json)); }, [filter]); return (
- setFilter(e.target.value)} /> + setFilter(e.target.value)} />
    {userCollection.map((user, index) => (
  • {user.name}
  • @@ -53,7 +53,7 @@ export const MyComponent = () => { A. Encapsulating as well the _UseEffect_ -_./src/demo.js_ +_./src/demo.tsx_ ```diff import React from "react"; diff --git a/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html b/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html +++ b/04-frameworks/01-react/03-react-hooks/07-custom-hook/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/Readme_es.md b/04-frameworks/01-react/03-react-hooks/08-pure-component/Readme_es.md index 37180b4b8..fa2004f5d 100644 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/Readme_es.md @@ -17,7 +17,7 @@ Vamos a ello. npm install ``` -- Vamos a pegar un ejemplo en _demo.js_, este código va tener dos +- Vamos a pegar un ejemplo en _demo.tsx_, este código va tener dos valores editables: _name_ y _lastname_ y vamos a tener un control hijo que sólo va a mostrar el _name_ (de hecho este componente sólo pedirá el campo nombre en las propiedades). diff --git a/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html b/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html +++ b/04-frameworks/01-react/03-react-hooks/08-pure-component/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html +++ b/04-frameworks/01-react/03-react-hooks/09-pure-component-callback/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/Readme.md b/04-frameworks/01-react/03-react-hooks/10-use-reducer/Readme.md index 108fa47e7..bfb699c6d 100644 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/Readme.md @@ -1,6 +1,6 @@ # 10 useReducer -## Resume +## Summary This example takes as a starting point _09-pure-component-callback_. diff --git a/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html b/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html +++ b/04-frameworks/01-react/03-react-hooks/10-use-reducer/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md index 79b9d4243..ac484cd7f 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/Readme.md @@ -1,6 +1,6 @@ # 11 useContext -## Resume +## Summary This example takes the _10-use-reducer_ example as a starting point. diff --git a/04-frameworks/01-react/03-react-hooks/11-use-context/index.html b/04-frameworks/01-react/03-react-hooks/11-use-context/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/11-use-context/index.html +++ b/04-frameworks/01-react/03-react-hooks/11-use-context/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/Readme.md b/04-frameworks/01-react/03-react-hooks/12-set-state-func/Readme.md index 7c723e258..0f1b944be 100644 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/Readme.md @@ -1,6 +1,6 @@ # 12 set state func -## Resume +## Summary This example takes the _11-use-context_ example as a starting point. diff --git a/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html b/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html +++ b/04-frameworks/01-react/03-react-hooks/12-set-state-func/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html b/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html +++ b/04-frameworks/01-react/03-react-hooks/13-async-closure/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/Readme_es.md b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/Readme_es.md index c59aeaf25..c5164ace8 100644 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/Readme_es.md @@ -12,7 +12,7 @@ vamos a usarlo para acceder a un nodo del dom. npm install ``` -- En _demo.js_ pegamos el siguiente código (fijate que aquí definimos +- En _demo.tsx_ pegamos el siguiente código (fijate que aquí definimos el _useRef_ y lo asociamos en el _div_ container). _./src/demo.tsx_ diff --git a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html +++ b/04-frameworks/01-react/03-react-hooks/14-use-ref-dom/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html +++ b/04-frameworks/01-react/03-react-hooks/15-memo-predicate/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html +++ b/04-frameworks/01-react/03-react-hooks/16-use-debug-value/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html +++ b/04-frameworks/01-react/03-react-hooks/17-why-did-you-update/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md b/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md index b7789b8e5..27078f513 100644 --- a/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/18-use-promise/Readme.md @@ -1,6 +1,6 @@ # 06 Ajax field change -## Resume +## Summary This example takes as a starting point the example \ \_05-component-update-render. @@ -16,7 +16,7 @@ As a bonus, we will check how to use Debounce (wait a little until the user stop npm install ``` -- Let's open the _demo.js_, and let's add an entry in the state that stores the current search filter, and another state in which we +- Let's open the _demo.tsx_, and let's add an entry in the state that stores the current search filter, and another state in which we are going to store a list of users. _./src/demo.tsx_ diff --git a/04-frameworks/01-react/03-react-hooks/18-use-promise/index.html b/04-frameworks/01-react/03-react-hooks/18-use-promise/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/18-use-promise/index.html +++ b/04-frameworks/01-react/03-react-hooks/18-use-promise/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme.md b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme.md index aa2a6c825..f607e3e7e 100644 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme.md +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme.md @@ -1,6 +1,6 @@ # 15 Promise unmounted -## Resume +## Summary This example takes as a starting point the example _14-use-ref-dom_. @@ -63,7 +63,7 @@ export const MyChildComponent = () => { - Now we want to launch an ajax request every time the user writes in the filter's text field (we'll add some latency). -_./src/demo.js_ +_./src/demo.tsx_ ```diff export const MyChildComponent = () => { diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme_es.md b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme_es.md index d755c4003..5e0597848 100644 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme_es.md +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/Readme_es.md @@ -28,7 +28,7 @@ npm install Primero creamos el armazon -_./src/demo.js_ +_./src/demo.tsx_ ```tsx import React from "react"; @@ -65,7 +65,7 @@ export const MyChildComponent = () => { - Ahora queremos lanzar una petición ajax cada vez que el usuario escriba en el campo de texto del filtro (añadiremos algo de latencia). -_./src/demo.js_ +_./src/demo.tsx_ ```diff export const MyChildComponent = () => { diff --git a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html index 050566921..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html +++ b/04-frameworks/01-react/03-react-hooks/99-promise-unmounted-R17/index.html @@ -3,7 +3,7 @@ - React App + React App - React hooks