Commit 4ab76811 by Miguel Mejía

Adds the documentation to work in frontend

parent 964f7b04
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
- [Tareas (tickets)](sections/tickets.md) 🎫 - ¡Aprende cómo gestionamos nuestras tareas! 📝 Este documento te mostrará cómo utilizamos los tickets para organizar y priorizar nuestro trabajo. - [Tareas (tickets)](sections/tickets.md) 🎫 - ¡Aprende cómo gestionamos nuestras tareas! 📝 Este documento te mostrará cómo utilizamos los tickets para organizar y priorizar nuestro trabajo.
- [Versionamiento de código fuente](sections/code-versioning.md) 💾 - ¡Domina el control de versiones! 💪 Este documento te enseñará cómo versionamos nuestro código fuente para mantener un historial de cambios y colaborar de manera segura. - [Versionamiento de código fuente](sections/code-versioning.md) 💾 - ¡Domina el control de versiones! 💪 Este documento te enseñará cómo versionamos nuestro código fuente para mantener un historial de cambios y colaborar de manera segura.
- [Proyectos back end](sections/backend-structure.md) ⚙️ - ¡Definamos como será la estructura de proyectos back end! - [Proyectos back end](sections/backend-structure.md) ⚙️ - ¡Definamos como será la estructura de proyectos back end!
- [Proyectos front-end](sections/frontend-structure.md) 💅 - Hagamos del front-end un lugar feliz y seguro :D
## Secciones pendientes 🚧 ## Secciones pendientes 🚧
...@@ -20,4 +21,5 @@ ...@@ -20,4 +21,5 @@
- [Bases de datos relacionales](sections/relational-dbs.md) 📊 - ¡Asegúrate de que tus bases de datos sean ordenadas, eficientes y seguras! - [Bases de datos relacionales](sections/relational-dbs.md) 📊 - ¡Asegúrate de que tus bases de datos sean ordenadas, eficientes y seguras!
--- ---
* volver al [inicio](/README.md)
- volver al [inicio](/README.md)
# 1. Introducción
Partimos de una idea fundamental: escribimos código no para que una máquina haga algo, sino para que otra persona entienda que se le pidió a la máquina que hiciera.
Aunque el rendimiento y la optimización son clave, la sostenibilidad del código es lo que debe guiar el cómo lo escribimos, y esta sostenibilidad está basada en la legibilidad y qué tan rápido una persona que no está familiarizada con el _codebase_ es capaz de comprenderlo. Es bonito cuando logramos algo con dos o tres líneas de código, pero si esas líneas parecen una validación de RegEx con look-ahead, nuestro momento HackerMan va a ser la miseria del equipo al mediano y largo plazo.
Hay miles de formas de escribir lo mismo en JavaScript/TypeScript y React, y no siempre estaremos disponibles para explicar nuestro razonamiento. Incluso, es muy probable que en una semana olvidemos por qué escribimos X y no Y. Por eso, es esencial unificar la forma en la que nos expresamos a través del código... Además, simpre será bonito cuando reducimos la carga cognitiva de las cosas.
Este documento es nuestro acuerdo para hablar el mismo idioma, ayudando a que cualquier persona que lea nuestro código se sienta familiarizada y pueda contribuir sin obstáculos.
---
[Volver al menú principal](../frontend-structure.md) | [Siguiente: Configuración del Entorno](./2-configuracion-del-entorno.md)
## 2. Configuración del Entorno
**TODO LO QUE HACEMOS DEBE ESTAR EN TYPESCRIPT**
### Herramienta de Formato
Para que el código de los proyectos en JS/TS/React/CualquierCompliantConEcmaScript tenga siempre el mismo formato sin importar quién lo escriba, usamos Prettier. Prettier es una herramienta opinionada, lo que significa que tiene su propio criterio para el formato del código, y como equipo, decidimos adoptarlo y respetarlo al pie de la letra
Aquí no hay debate: si a Linus Torvalds le gusta la indentación de 8 espacios y a ti te gusta la de 4, pero Prettier dice que 2, nos vamos con 2. No hay discusión, Prettier es palabra sagrada. Esto nos libera de discusiones sobre estilo y nos permite enfocarnos en lo que importa.
Puedes integrarlo en tu editor con los plugins oficiales. Si no, de seguro habremos dispuesto de un script dentro del package.json para darle formato al código: usualmente `<npm/pnpm/yarn/administrador de paquetes> format` harán ese trabajo.
### La seguridad antes que la policía
Prettier es nuestra brújula de estilo y ESLint es quien evita que la caguemos antes de tiempo con pendejadas. Su propósito es detectar problemas de calidad, consistencia y posibles errores antes de que lleguen al código. Nuestra configuración combina las recomendaciones estándar de Airbnb, las de react y la ultima palabra la da prettier para evitar conflictos en las reglas...
```typescript
extends: [
"airbnb",
"airbnb-typescript",
"plugin:react-hooks/recommended",
"plugin:prettier/recommended",
],
```
Pero en esta área nuestro equipo si tiene opiniones y acuerdos que modifican las reglas base y responden a el cómo vemos el código y las experiencias que hemos tenido.
#### Algunas de nuestras reglas clave
**Evitamos la anidación excesiva**. La regla `no-nested-ternary` nos prohíbe usar operadores ternarios dentro de otros, ya que reducen la legibilidad y aumentan la carga cognitiva.
**Corchetes, siempre**, `curly` nos obliga a usar llaves en todos los bloques de control, como en los `if` y `for`. Así, evitamos errores al añadir más líneas de código en el futuro.
**¡Exportaciones nombradas, siempre!** Con `import/no-default-export` nos aseguramos de que cada archivo solo tenga exportaciones con nombre. Esto facilita el autocompletado y reduce los conflictos de nombres.
**En React, componentes declarativos, funciones internas de flecha,** los componentes de React deben ser declaraciones de función (`function Componente() {}`), lo que ayuda a la legibilidad y la depuración. Sin embargo, para callbacks y funciones internas del componente, preferimos las funciones flecha (`() => {}`) por su sintaxis concisa y su manejo más predecible de `this`.
**En TypeScript...** funciones de flecha, para evitarnos dolores de cabeza con el this, aunque sea más idiomática function.
#### Nuestro ruleset
```typescript
"rules": {
// === REGLAS DE REACT Y HOOKS ===
// Desactiva la regla que requiere importar 'React' en cada archivo con JSX. Esto es estándar en React 17+.
"react/react-in-jsx-scope": "off",
// Desactiva la restricción de 'prop spreading' (ej. <Componente {...props} />).
"react/jsx-props-no-spreading": "off",
// Define el estilo de los componentes: `function declaration` para los nombrados y `arrow function` para los anónimos.
"react/function-component-definition": [
"error",
{
"namedComponents": "function-declaration",
"unnamedComponents": "arrow-function"
}
],
// === REGLAS DE IMPORTACIÓN ===
// Evita ciclos de importación (dependencias circulares).
"import/no-cycle": "error",
// Asegura que las importaciones de módulos locales no tengan extensión de archivo.
"import/extensions": [
"error",
"ignorePackages",
{
"ts": "never",
"tsx": "never",
"js": "never",
"jsx": "never"
}
],
// Prohíbe todas las exportaciones 'default' en la base de código.
"import/no-default-export": "error",
// Desactiva la regla que preferiría exportaciones default de Airbnb.
"import/prefer-default-export": "off",
// Prohíbe las importaciones usando rutas relativas ('../') para forzar el uso de rutas absolutas desde 'src/' y alias.
"import/no-relative-parent-imports": "error",
// Solo permite dependencias de desarrollo en archivos de configuración y test.
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": [
"**/*.test.{ts,tsx}",
"**/*.spec.{ts,tsx}",
"vite.config.ts",
"jest.config.{js,ts}"
]
}
],
// === REGLAS DE TYPESCRIPT ===
// Prefiere la sintaxis concisa para los tipos de función.
"@typescript-eslint/prefer-function-type": "error",
// Muestra un error si una variable no es usada, ignorando las que empiezan con un guion bajo '_'.
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
// Prefiere las importaciones de tipo (`import type`) para claridad.
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports"
}
],
// === REGLAS DE ESTILO Y LÓGICA GENERAL ===
// Define el estilo de las funciones.
"func-style": [
"error",
"declaration",
{
"allowArrowFunctions": true
}
],
// Obliga a usar `arrow functions` para callbacks.
"prefer-arrow-callback": [
"error",
{
"allowNamedFunctions": true,
"allowUnboundThis": true
}
],
// Prohíbe el uso de operadores ternarios anidados.
"no-nested-ternary": "error",
// Obliga a usar llaves en todos los bloques de control
"curly": "error",
// Permite `console.warn` y `console.error` pero no `console.log`.
"no-console": [
"warn",
{
"allow": ["warn", "error"]
}
],
// Prohíbe `var` y exige `const` o `let`.
"no-var": "error",
// Exige `const` si la variable no se reasigna.
"prefer-const": "error"
}
}
```
---
[Anterior: Introducción](./1-introduccion.md) | [Volver al menú principal](../frontend-structure.md) | [Siguiente: Convenciones Generales](./3-convenciones-generales.md)
\ No newline at end of file
# 3. Convenciones Generales
## Orden del código
**Módulos**: Siempre trabajaremos con el sistema de Módulos de ECMAScript (ESM) en nuestro código. Aunque aún existen librerías en CommonJS (CJS), podemos usarlas como módulos e importarlas sin usar la sintaxis de `require`.
**Evitar el entorno global**: Usemos las capacidades de los módulos para mantener nuestro entorno global limpio. No hay necesidad de declarar variables globales que ensucien todo y generar conflictos.
- **Clases con propósito**: No creemos clases solo para encapsular un conjunto de variables y funciones, eso lo puede hacer mejor un módulo. Las clases deben cumplir un propósito de arquitectura, como implementar un patrón de diseño (di tu un _singleton_) o manejar un estado interno complejo y persistente.
## Una línea, una acción
Buscamos que cada línea de código tenga un propósito único y fácil de entender. Cuando una sola línea hace demasiadas cosas, se vuelve difícil de leer y peor de depurar. Por eso, preferimos la claridad sobre la concisión.
Esto explica porqué evitamos los ternarios anidados y usamos llaves en todos nuestros bloques de control (incluso en los `if` de una sola línea), lo que hace que el código sea predecible y reduce los errores a largo plazo.
## Nomenclatura
Una de las cosas más difíciles en la programación es asignar buenos nombres de forma consistente. La razón es simple: un buen nombre reduce la necesidad de explicaciones. Buscamos nombres que le digan a cualquiera lo que están viendo sin necesidad de comentarios.
- **Idioma**: Aunque respetamos el idioma en el que hablamos, el "espanglish" puede ser muy molesto y aumenta la carga cognitiva. Dado que los lenguajes de programación que usamos están en inglés, hemos acordado usar este idioma en nuestro código.
- **Variables y funciones**: Usamos **`camelCase`**. Los nombres de variables deben ser sustantivos que describan su contenido (ej., `userId`, `userName`), y los de las funciones, verbos que indiquen lo que hacen (ej., `fetchUsers`, `calculateTotal`, `getSomeShit`)... tener cuidado con palabras genéricas como `info` o `data` y de ser posible optar por algo más descriptivo de la información que contienen.
- **Tipos, clases y componentes**: Usamos **`PascalCase`**. Esto ayuda a diferenciarlos del resto del código (ej., `UserType`, `ProductCard`).
- **Constantes de configuración**: Usamos **`SCREAMING_SNAKE_CASE`**. Son constantes que se usan para una configurar un comportamiento del código, su nombre en mayúsculas debe dejar muy claro la info que contienen (ej., `API_URL`, `MAX_RETRIES`, `I_AM_A_MAGIC_NUMBER`).
## Librerías Externas
Importar debe suceder solo cuando algo es realmente necesario. Evitamos importar por importar y nos aseguramos de que las librerías que usamos estén bien mantenidas y sean de alta calidad.
Un ejemplo de lo que puede salir mal es el caso de **`left-pad`**. Una librería con una función simple (no más de cinco líneas de código), que, al ser eliminada de NPM(Luego de eso se reforzó la política de no borrado de NPM), causó que miles de proyectos dejaran de compilar. [El chisme completo](https://en.wikipedia.org/wiki/Npm_left-pad_incident).
**Cada dependencia es una responsabilidad.**
Por lo tanto:
- Solo importamos cuando la lógica del proyecto no depende de la importación.
- Solo importamos si hemos confirmado que no hay una forma directa o clara de realizar lo que necesitamos con nuestro propio código dentro del tiempo que disponemos.
- Solo importamos librerías que tengan soporte activo (al menos un año).
- Solo importamos librerías con tipado en TypeScript nativo para integrarlas mejor.
## Accesibilidad
Construir una interfaz de usuario no es solo cuestión de estética. La accesibilidad es fundamental para que nuestras aplicaciones puedan ser usadas por cualquier persona, considerando sus diversas capacidades físicas, cognitivas, sociales, contextuales y tecnológicas.
**HTML Semántico**: Usa las etiquetas correctas (`<button>`, `<nav>`, `<article>`, ... ) en lugar de `<div>` como mantequilla en restaurante francés. El HTML semántico es clave para construir aplicaciones web accesibles desde el inicio, ayudando a los lectores de pantalla a entender la estructura de la página, facilitando la navegación con tecnologías asistivas y mejorando el SEO. [Aquí hay una pequeña guía](https://webdesign.solomon.ng/html-and-css/semantic-html/semantic-html.html).
**Atributos `aria-*`**: Una vez que nuestro documento está bien estructurado, los usuarios con tecnologías asistivas deben ser capaces de comprender los cambios que introducimos en el documento a través de las interacciones. Aquí es donde entra `aria-*`, que complementa lo que el HTML no cubre. Sin embargo, _no aria is better than wrong aria_(Es mejor no tener aria a tener uno mal escrito). Si no entiendes el atributo, investiga antes de usarlo. [Esta es una buena introducción a ARIA](https://accessibilityfordevelopers.com/guide-to-aria/) y [aquí está la guía de MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA), que es más amigable que las especificaciones de la W3C.
**Manejo de Foco**: Es clave que todo lo que se puede hacer con el _mouse_ también se posible hacerlo con el teclado. Asegúrate de que los elementos sean enfocables y que el orden del foco sea lógico.
## El texto de la interfaz de usuario
Para facilitar el soporte, la internacionalización y las actualizaciones, se debe evitar "quemar" el texto directamente en el código. La práctica preferida es guardarlo en un archivo JSON, en la última carpeta común que use este texto, o al mismo nivel del directorio donde es usado. Así, tenemos una fuente única y consistente para el texto usado por el padre y todos sus hijos o todos los hermanos, y cualquier cambio de texto sucede en un solo lugar sin tener que modificar el código funcional.
## Comentarios solo cuando el código no lo explica todo
Idealmente, los nombres y la estructura de nuestro código deberían ser tan claros que hagan de los comentarios algo innecesario. Sin embargo, rara vez nuestro código alcanza ese nivel de "iluminación", y necesitamos explicar el _porqué_ de una solución. Comentemos lo menos posible y, cuando lo hagamos, sigamos estos parámetros:
- **Solo lo esencial**: Los comentarios deben usarse para explicar la razón de una decisión, no lo que el código está haciendo.
- **Etiquetas**: Usar etiquetas estandarizadas ayuda a que los comentarios sean fáciles de encontrar y den contexto a quien los lee en el futuro:
- **`NOTE:`**: Para dejar una nota importante.
- **`WARN:`**: Para advertir de un posible problema.
- **`HACK:`**: Para explicar soluciones temporales que deben ser atendidas pronto.
- **`TODO:`**: Para marcar una tarea pendiente.
- **`FIX:`**: Para indicar que algo está roto y necesita ser arreglado.
- **Documentación (TSDoc)**: Úsalo solo para funciones y métodos que se exportan y son usados por otros archivos. Como regla general, piensa en qué información te gustaría tener disponible en las ventanas del LSP de tu editor de texto cuando escribes código. No es necesario explicar una función que solo es usada dentro del mismo archivo.
## Aduana: Importaciones y exportaciones
El orden de las importaciones es crucial para la legibilidad y una estructura consistente en todo nuestro codigo, el orden acordado es, primero las **librerías externas** y dependencias de `node_modules`, como `leaflet` y `axios`, seguidas por los **módulos internos**, que son los archivos de nuestro _codebase_, lo que hay dentro de `src/`, estos últimos siempre deben ser importados con rutas absolutas o alias.
Además, como equipo, evitamos las exportaciones `default` para tener un mejor seguimiento de los elementos. Esto nos asegura que siempre importemos con el nombre exacto (`import { Button } from '...'`), o que si cambiamos el nombre, sea de forma consciente, evitando confusiones.
### Importaciones Dinámicas
Evitamos las importaciones dinámicas (`import('someShit')`) a menos que haya una razón clara para hacerlo, como la optimización, rendimiento o _code splitting_, y en estos casos debe estar documentada la razón. Implementarla sin atención puede complicar el seguimiento de los módulos.
---
[Volver al menú principal](../frontend-structure.md) | [Siguiente: Buenas Prácticas en TypeScript](./4-buenas-practicas-en-typescript.md)
# 4. Buenas Prácticas en TypeScript
Sí, TypeScript es un linter glorificado, pero es el que nos permite movernos de forma segura dentro del despelote que armó el uso desmedido de JavaScript en la web y las ganas de meterlo hasta en la cafetera. No es solo una barrera de seguridad, es una herramienta para construir aplicaciones más robustas y fáciles de entender.
## Explicar lo suficiente
TypeScript puede inferir tipos por sí solo, pero no siempre es la mejor práctica. En algunos casos, el tipado explícito es fundamental para la claridad y la legibilidad.
**Tipado inferido**: Lo usamos en casos obvios, donde el tipo es claro a simple vista (ej., `const name = 'Andrés'`). A menudo, los tipos inferidos pueden ser más precisos que los explícitos. En este caso, el tipo de `name` sería la cadena literal `'Andrés'`, que es más precisa que `string`.
**Tipado explícito**: Es esencial para funciones, propiedades de objetos o variables que podrían tener más de un tipo (ej., `const data: string[] | number[]`). También lo usamos cuando el tipo no es tan fácil de inferir, como en un objeto literal, o cuando sabemos que el valor va a ser asignado por un desarrollador, para no correr el riesgo que un cambio de tipo `42` a `"42"` nos rompa el programa. Este tipado explícito nos ayuda a documentar el código sin necesidad de más comentarios.
**Retornos Tipados**: Aunque TypeScript puede inferir muy bien el tipo de retorno, hacer explícitos los tipos del retorno en la firma de la función, ayuda a dar una idea clara de lo que hace antes de analizar su funcionamiento interno.
## Interfaces y Tipos: ¿Cuál y cuándo?
La elección entre `interface` y `type` puede ser confusa, y cada 8 días puede cambiar la forma en la que uno tiparía un objeto, pero generalmente...
**Type**: Es el la declaración base, es la más flexible y te permite crear uniones (`|`), intersecciones (`&`) y definir tipos primitivos o literales, al igual que objetos.
**Interface**: Su uso es más cercano a las Clases por su posibilidad de ser extensible, lo cual nos puede servir para crear jerarquías de tipos.
## Arrays y Genéricos
**Tipado de _arrays_**: Preferimos la sintaxis `string[]` en lugar de `Array<string>`. Es más concisa, fácil de leer y la convención más común en la comunidad.
**Construcción de genéricos**: Úsalos para crear componentes o funciones que pueden trabajar con una variedad de tipos de datos sin perder el tipado. Un buen genérico no solo tipa la entrada, sino que también tipa la salida, asegurando que la información que retorna la función sea del mismo tipo que recibió.
```typescript
// Mal ejemplo: usa 'any' y pierde el tipado del array.
function getItem(array: any[], index: number): any {
return array[index];
}
// Buen ejemplo: usa un tipo genérico 'T' para mantener el tipado.
// La función `getItem` siempre devolverá un elemento del mismo tipo que recibió.
function getItem<T>(array: T[], index: number): T {
return array[index];
}
const names = ['Andrés', 'Sofía', 'Pedro'];
const aName = getItem(names, 1); // aName es de tipo string, no 'any'.
```
## Archivos de definición de tipos
Para mantener el proyecto organizado, el alcance de los tipos es crucial. Cuando un tipo tiene un alcance limitado a un solo archivo, lo declaramos en ese mismo archivo. Esto mantiene el código cohesivo.
Si un tipo se usa en múltiples archivos, lo extraemos a un archivo `*.types.ts` en la carpeta más cercana que lo contenga. Esta práctica asegura que tengamos una única fuente de verdad, lo que mejora la consistencia y la sostenibilidad del código.
## Vamo' a calmarno'
Typescript es un linter, no vale la pena pasar más tiempo construyendo tipos perfectos que escribiendo la lógica de lo que estamos trabajando. Si una solución simple funciona, usarla sin miedo. Las abstracciones innecesarias y la "masturbación de tipos" solo añaden confusión y complican el código.
## Constantes con enums y posibilidades con literales
Para mantener el código ordenado, siempre que sea posible podemos agrupar el tipado de contantes relacionadas en enums
```typescript
enum Status {
Loading = 'LOADING',
Success = 'SUCCESS',
Error = 'ERROR',
}
const currentStatus = Status.Loading;
```
El uso de literales es recomendado para un conjunto de valores fijos y acotados. Por ejemplo: `type UserRole = 'admin' | 'guest'`.
## `any`, `unknown` y `never`
**`any`**: **NO USARLO NUNCA**, salvo que estemos en proceso de migrar algo de JS a TS. Es la peor práctica y anula completamente el propósito de TypeScript.
**`unknown`**: Este es el tipo de dato que debes usar cuando no sabes qué tipo va a entrar. Después, usa _type narrowing_ para trabajar con el valor.
**`never`**: Se usa para indicar que una función **nunca** retorna un valor (ej., una función que siempre lanza un error o entra en un bucle infinito).
## Helpers y Tipos Utilitarios
**`type guards`**: Hacer uso de estas funciones que validan y reducen el tipo de un valor. Suelen tener esta firma: `(myValue: unknown): myValue is Type`. Son cruciales para trabajar con datos que no tienen un tipo seguro.
**`Partial`, `Pick`, `Omit`, and shit...**: Los tipos utilitarios de TypeScript son poderosos. En lugar de crear un tipo nuevo cada vez que necesitas una variante de un tipo ya existente, usar utilitarios.
---
[Volver al menú principal](../frontend-structure.md) | [Siguiente: Buenas Prácticas en React](./5-buenas-practicas-en-react.md)
# Guía de estilo para desarrollo en React con TS
## TL;DR
Instale ESLint y Prettier, utilice el config y las reglas de lint suministradas y el default de Prettier.
## Índice de Contenidos
1. [Introducción](./front/1-introduccion.md)
2. [Configuración del Entorno](./front/2-configuracion-del-entorno.md)
- [Herramienta de Formato](./front/2-configuracion-del-entorno.md#herramienta-de-formato)
- [La seguridad antes que la policía](./front/2-configuracion-del-entorno.md#la-seguridad-antes-que-la-policía)
3. [Convenciones Generales](./front/3-convenciones-generales.md)
- [Orden del código](./front/3-convenciones-generales.md#orden-del-código)
- [Una línea, una acción](./front/3-convenciones-generales.md#una-línea-una-acción)
- [Nomenclatura](./front/3-convenciones-generales.md#nomenclatura)
- [Librerías Externas](./front/3-convenciones-generales.md#librerías-externas)
- [Accesibilidad](./front/3-convenciones-generales.md#accesibilidad)
- [El texto de la interfaz de usuario](./front/3-convenciones-generales.md#el-texto-de-la-interfaz-de-usuario)
- [Comentarios solo cuando el código no lo explica todo](./front/3-convenciones-generales.md#comentarios-solo-cuando-el-código-no-lo-explica-todo)
- [Aduana: Importaciones y exportaciones](./front/3-convenciones-generales.md#aduana-importaciones-y-exportaciones)
4. [Buenas Prácticas en TypeScript](./front/4-buenas-practicas-en-typescript.md)
- [Explicar lo suficiente](./front/4-buenas-practicas-en-typescript.md#explicar-lo-suficiente)
- [Interfaces y Tipos: ¿Cuál y cuándo?](./front/4-buenas-practicas-en-typescript.md#interfaces-y-tipos-cuál-y-cuándo)
- [Arrays y Genéricos](./front/4-buenas-practicas-en-typescript.md#arrays-y-genéricos)
- [Archivos de definición de tipos](./front/4-buenas-practicas-en-typescript.md#archivos-de-definición-de-tipos)
- [Vamo' a calmarno'](./front/4-buenas-practicas-en-typescript.md#vamo-a-calmarno)
- [Constantes con enums y posibilidades con literales](./front/4-buenas-practicas-en-typescript.md#constantes-con-enums-y-posibilidades-con-literales)
- [`any`, `unknown` y `never`](./front/4-buenas-practicas-en-typescript.md#any-unknown-y-never)
- [Helpers y Tipos Utilitarios](./front/4-buenas-practicas-en-typescript.md#helpers-y-tipos-utilitarios)
5. [Buenas Prácticas en React](./front/5-buenas-practicas-en-react.md)
- [Componentes de Función: La preferencia del equipo](./front/5-buenas-practicas-en-react.md#componentes-de-función-la-preferencia-del-equipo)
- [Estructura y Organización](./front/5-buenas-practicas-en-react.md#estructura-y-organización)
- [Props: Cómo pasar y gestionar propiedades](./front/5-buenas-practicas-en-react.md#props-cómo-pasar-y-gestionar-propiedades)
- [Manejo de Estados: Estrategias claras](./front/5-buenas-practicas-en-react.md#manejo-de-estados-estrategias-claras)
- [Sincronización (`useEffect`)](./front/5-buenas-practicas-en-react.md#sincronización-useeffect)
- [useMemo y useCallback](./front/5-buenas-practicas-en-react.md#usememo-y-usecallback)
- [Código ordenado](./front/5-buenas-practicas-en-react.md#código-ordenado)
- [Fragmentos y Portales](./front/5-buenas-practicas-en-react.md#fragmentos-y-portales)
- [Handlers (Funciones para manejar eventos de usuario)](./front/5-buenas-practicas-en-react.md#handlers-funciones-para-manejar-eventos-de-usuario)
- [Seguridad y Buenas Prácticas](./front/5-buenas-practicas-en-react.md#seguridad-y-buenas-prácticas)
- [Manejo de errores](./front/5-buenas-practicas-en-react.md#manejo-de-errores)
6. El CSS deja de ser tan feo cuando lo entiendes (guía en desarrollo)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment