From 6c7771aa6ae75331572b44c508dd703299a865c6 Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 19:04:47 +0200 Subject: [PATCH 1/2] update react-03-react-hooks-examples-from-0-to-6 --- .../03-react-hooks/00-boilerplate/.babelrc | 7 - .../03-react-hooks/00-boilerplate/Readme.md | 131 ++---------------- .../00-boilerplate/Readme_es.md | 125 ++--------------- .../src => 00-boilerplate}/index.html | 9 +- .../00-boilerplate/package.json | 46 ++---- .../00-boilerplate/src/index.tsx | 4 +- .../00-boilerplate/tsconfig.json | 25 ++-- .../00-boilerplate/vite.config.ts | 7 + .../00-boilerplate/webpack.config.js | 54 -------- .../03-react-hooks/01-use-state/.babelrc | 7 - .../03-react-hooks/01-use-state/Readme.md | 8 +- .../03-react-hooks/01-use-state/Readme_es.md | 18 +-- .../src => 01-use-state}/index.html | 9 +- .../03-react-hooks/01-use-state/package.json | 46 ++---- .../03-react-hooks/01-use-state/tsconfig.json | 25 ++-- .../01-use-state/vite.config.ts | 7 + .../01-use-state/webpack.config.js | 54 -------- .../02-use-state-object/.babelrc | 7 - .../02-use-state-object/Readme.md | 13 +- .../02-use-state-object/Readme_es.md | 4 +- .../02-use-state-object/{src => }/index.html | 9 +- .../02-use-state-object/package.json | 46 ++---- .../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 -------- .../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 | 29 ++-- .../src => 03-component-mount}/index.html | 9 +- .../03-component-mount/package.json | 23 +++ .../readme_es.md | 39 +++--- .../src/app.tsx | 0 .../src/demo.tsx | 0 .../src/index.tsx | 0 .../src/styles.css | 0 .../03-component-mount/tsconfig.json | 19 +++ .../03-component-mount/vite.config.ts | 7 + .../Readme.md | 20 +-- .../Readme_es.md | 20 +-- .../04-component-unmount/index.html | 13 ++ .../04-component-unmount/package.json | 23 +++ .../src/app.tsx | 0 .../04-component-unmount/src/demo.tsx | 42 ++++++ .../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/src/index.html | 12 -- .../04-component_unmount/src/styles.css | 3 - .../04-component_unmount/tsconfig.json | 18 --- .../04-component_unmount/webpack.config.js | 54 -------- .../05-component-update-render/.babelrc | 7 - .../05-component-update-render/Readme.md | 11 +- .../05-component-update-render/Readme_es.md | 59 +++++++- .../05-component-update-render/index.html | 13 ++ .../05-component-update-render/package.json | 46 ++---- .../05-component-update-render/src/demo.tsx | 18 ++- .../05-component-update-render/src/index.html | 12 -- .../05-component-update-render/tsconfig.json | 25 ++-- .../05-component-update-render/vite.config.ts | 7 + .../webpack.config.js | 54 -------- 67 files changed, 505 insertions(+), 1048 deletions(-) delete mode 100644 04-frameworks/01-react/03-react-hooks/00-boilerplate/.babelrc rename 04-frameworks/01-react/03-react-hooks/{01-use-state/src => 00-boilerplate}/index.html (54%) 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 delete mode 100644 04-frameworks/01-react/03-react-hooks/01-use-state/.babelrc rename 04-frameworks/01-react/03-react-hooks/{00-boilerplate/src => 01-use-state}/index.html (54%) 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 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 (54%) 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 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 (74%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload/src => 03-component-mount}/index.html (54%) 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 (77%) 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.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{00-boilerplate => 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 (78%) rename 04-frameworks/01-react/03-react-hooks/{04-component_unmount => 04-component-unmount}/Readme_es.md (88%) 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.tsx (100%) rename 04-frameworks/01-react/03-react-hooks/{03-component-did-onload => 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/src/index.html delete mode 100644 04-frameworks/01-react/03-react-hooks/04-component_unmount/src/styles.css 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 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 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/05-component-update-render/vite.config.ts delete mode 100644 04-frameworks/01-react/03-react-hooks/05-component-update-render/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..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,125 +1,16 @@ -# 03 Webpack React +# 02 Vite boiler plate - 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 _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 -``` - - - - - - - +Boiler plate extracted from _02-base/02-vite-react_. +Below, main points. For more info, check the original repo or the Vite module. +- 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). +- `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 bb34f2812..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,119 +1,16 @@ -# 03 Webpack React +# 02 Vite boiler plate - React ## Resumen -Este ejemplo toma como punto de partida el ejemplo _02-webpack-boiler_. +Boiler plate extraído de _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. +A continuación, puntos principales. Para más info, acudir a repo original o módulo de vite. -## 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_ - -```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 -``` +- 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, 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`. diff --git a/04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html similarity index 54% rename from 04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html rename to 04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html index a3d74b719..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/01-use-state/src/index.html +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App - React hooks +
+ 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..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 @@ -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/03-react-hooks/00-boilerplate/src/index.tsx b/04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.tsx index 7e439b87e..f323553ef 100644 --- 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 @@ -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/03-react-hooks/00-boilerplate/tsconfig.json b/04-frameworks/01-react/03-react-hooks/00-boilerplate/tsconfig.json index 3312b5f1e..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 @@ -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/00-boilerplate/vite.config.ts b/04-frameworks/01-react/03-react-hooks/00-boilerplate/vite.config.ts new file mode 100644 index 000000000..a0024d88e --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/00-boilerplate/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/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 - }), - ], -}; 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/Readme.md b/04-frameworks/01-react/03-react-hooks/01-use-state/Readme.md index 96b95eb8e..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. @@ -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..32dc2c7f7 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 @@ -2,7 +2,7 @@ ## Resumen -Este ejemplo toma como punto de partida el ejemplo _00-boiler-plate_. +Este ejemplo toma como punto de partida el ejemplo _00-boilerplate_. Vamos a crear un componente que por un lado muestre un nombre en un **h4**, y por otro permita editarlo utilizando un **input**. @@ -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/00-boilerplate/src/index.html b/04-frameworks/01-react/03-react-hooks/01-use-state/index.html similarity index 54% rename from 04-frameworks/01-react/03-react-hooks/00-boilerplate/src/index.html rename to 04-frameworks/01-react/03-react-hooks/01-use-state/index.html index a3d74b719..fe100be04 100644 --- a/04-frameworks/01-react/03-react-hooks/00-boilerplate/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 - React hooks +
+ 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..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 @@ -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/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 - }), - ], -}; 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/Readme.md b/04-frameworks/01-react/03-react-hooks/02-use-state-object/Readme.md index 5b19a0fb3..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. @@ -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/src/index.html b/04-frameworks/01-react/03-react-hooks/02-use-state-object/index.html similarity index 54% 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..fe100be04 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 - React hooks +
+ 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..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 @@ -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/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 - }), - ], -}; 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 74% 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 index d4824f6b0..3ccf0b864 100644 --- 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 @@ -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-did-onload/src/index.html b/04-frameworks/01-react/03-react-hooks/03-component-mount/index.html similarity index 54% 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/index.html index a3d74b719..fe100be04 100644 --- 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/index.html @@ -1,12 +1,13 @@ - - - - My App Example + + + React App - React hooks +
+ 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..9ee970f00 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/03-component-mount/package.json @@ -0,0 +1,23 @@ +{ + "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" + } +} 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 77% 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 index ea72abb86..603f93316 100644 --- 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 @@ -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/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.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/00-boilerplate/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/00-boilerplate/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 78% 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..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-dom-onload_ 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 similarity index 88% 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..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 @@ -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. @@ -39,10 +39,10 @@ _./src/demo.tsx_ ```diff return ( <> - {visible &&

Hello

} + + {visible &&

Hello

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

Hello

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

Hello

} ++ {visible && } ); }; ``` -- 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 new file mode 100644 index 000000000..fe100be04 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/index.html @@ -0,0 +1,13 @@ + + + + + + React App - React hooks + + + +
+ + + 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..9ee970f00 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/04-component-unmount/package.json @@ -0,0 +1,23 @@ +{ + "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" + } +} 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.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/03-component-did-onload/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/03-component-did-onload/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/src/index.html b/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.html deleted file mode 100644 index a3d74b719..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - My App Example - - -
- - 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 deleted file mode 100644 index 74dc08fbb..000000000 --- a/04-frameworks/01-react/03-react-hooks/04-component_unmount/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.my-text { - color: blue; -} 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/.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.md b/04-frameworks/01-react/03-react-hooks/05-component-update-render/Readme.md index 567548c0a..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,8 +1,8 @@ # 05 Component update render -## Resume +## Summary -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. @@ -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 3055849a7..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 @@ -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. @@ -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 @@ -26,10 +26,10 @@ export const MyComponent = () => { return ( <> - {visible && } + {visible && } ); }; @@ -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(() => { @@ -93,8 +93,53 @@ React.useEffect(() => { - Si ejecutamos podemos ver como se invocan las dos funciones. -```bash -npm start +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]); ``` # ¿Te apuntas a nuestro máster? 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..fe100be04 --- /dev/null +++ b/04-frameworks/01-react/03-react-hooks/05-component-update-render/index.html @@ -0,0 +1,13 @@ + + + + + + React App - React hooks + + + +
+ + + 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..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 @@ -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/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/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/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 - }), - ], -}; From 4a87c5fde3843262bdbed9b9b6718b3d46e91bbc Mon Sep 17 00:00:00 2001 From: Miguel Angel Chimali Cobano Date: Tue, 2 Sep 2025 19:22:36 +0200 Subject: [PATCH 2/2] misspelling --- .../01-react/03-react-hooks/02-use-state-object/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6fc56879c..88e3cdaa0 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 @@ -83,7 +83,7 @@ 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 while the function is being -executed, once the component is rerended this value is be lost. +executed, once the component is rerendered this value is 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