Skip to content

Commit

Permalink
Merge pull request #2291 from breatheco-de/master
Browse files Browse the repository at this point in the history
Review of useReducer lesson
  • Loading branch information
alesanchezr authored May 9, 2024
2 parents 3eaa6e7 + 8d0f2cc commit d94d4af
Show file tree
Hide file tree
Showing 5 changed files with 705 additions and 47 deletions.
151 changes: 151 additions & 0 deletions src/content/lesson/database-normalization.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
## Conceptos básicos

Cuando hablamos de bases de datos relacionales La principal ventaja que se nos viene a la mente es la integridad de los datos estas bases de datos permiten distribuir la información en Tablas distintas para agrupar información Según sea pertinente y crear relaciones entre las tablas para asociar la información. sin embargo para mantener la integridad es necesario cumplir ciertos estándares a la hora de diseñar nuestras tablas Necesitamos que la estructura sea pertinente a los datos que queremos almacenar y que garantice la integridad de la información así como su consistencia y evite Tener información redundante innecesaria.

Para ello existe la normalización de base de datos. se trata de cinco formas normales que de cumplirlas tu base de datos garantizará la integridad de la información y la optimización a la hora de hacer consultas. las formas cuatro y cinco generalmente se contemplan para escenarios más avanzados y de mayor complejidad, para la mayoría de los casos bastará con cumplir las tres primeras formas normales que cubriremos a continuación en este artículo.

Antes de hablar de las formas normales debemos manejar algunos conceptos fundamentales.

El primer concepto es entidad, se trata de una abstracción de un objeto de la realidad o de un proceso de la organización cuyos datos deben ser almacenados en la base de datos de manera agrupada y correlacionada.

El segundo es llave primaria, se trata de un atributo o columna que sirve para identificar de manera inequívoca a una entidad dentro de una tabla.


## Primera forma Normal - 1NF

Para que una tabla cumpla con la primera forma normal debe cumplir los siguientes parámetros:



* Cada celda debe tener un único valor
* Debe haber una llave primaria para identificar cada entidad
* No debe haber filas o columnas duplicadas

Si por ejemplo tenemos una tabla de pedidos de productos de la siguiente forma:


<table>
<tr>
<td>Pedido
</td>
<td>Detalle
</td>
<td>Cliente
</td>
</tr>
<tr>
<td>1
</td>
<td>2 Zapatos
</td>
<td>Pedro
</td>
</tr>
<tr>
<td>1
</td>
<td>3 Pantalones
</td>
<td>Pedro
</td>
</tr>
<tr>
<td>2
</td>
<td>1 Bolso
</td>
<td>María
</td>
</tr>
<tr>
<td>3
</td>
<td>1 Camisa
</td>
<td>Ana
</td>
</tr>
</table>


Podemos notar que la columna detalle contiene dos datos importantes para el pedido la cantidad y la información del producto. de la misma forma podemos notar como si bien Podemos identificar el pedido con el ID no ocurre lo mismo en el caso de los productos y del cliente puesto que solo tenemos un nombre que No necesariamente es único para cada uno y puede ser repetido.


<table>
<tr>
<td>Pedido
</td>
<td>IdProducto
</td>
<td>NombreProducto
</td>
<td>Cantidad
</td>
<td>IdCliente
</td>
<td>Cliente
</td>
</tr>
<tr>
<td>1
</td>
<td>1z
</td>
<td>Zapatos
</td>
<td>2
</td>
<td>1
</td>
<td>Pedro
</td>
</tr>
<tr>
<td>1
</td>
<td>3P
</td>
<td>Pantalones
</td>
<td>3
</td>
<td>1
</td>
<td>Pedro
</td>
</tr>
<tr>
<td>2
</td>
<td>2B
</td>
<td>Bolso
</td>
<td>1
</td>
<td>2
</td>
<td>María
</td>
</tr>
<tr>
<td>3
</td>
<td>2Z
</td>
<td>Zapatos
</td>
<td>1
</td>
<td>3
</td>
<td>Ana
</td>
</tr>
</table>


Ahora podemos ver cómo no solo el pedido se puede identificar con su ID sino que también Contamos con ideas para el producto y el cliente de manera que cada una de estas entidades pueda ser identificada.


## Segunda forma normal - 2NF.
66 changes: 35 additions & 31 deletions src/content/lesson/optimize-react-components-usereducer.es.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Qué es y como usar el hook useReducer en React.js"
subtitle: "Aprende a usar el hook useReducer en React.js y cómo funciona, comparalo con otras alternativas como redux, flux, entre otras."
title: "¿Qué es y cómo usar el hook useReducer en React.js"
subtitle: "Aprende a usar el hook useReducer en React.js y cómo funciona, compáralo con otras alternativas como redux, flux, entre otras."
cover: "https://www.desktopbackground.org/p/2013/09/13/637935_nasa-wallpapers_1600x1200_h.jpg"
textColor: "white"
date: "2024-01-16T16:45:31-04:00"
Expand All @@ -12,47 +12,49 @@ status: "draft"
## Que es el useReducer

Los hooks empezaron a existir en react desde la versión 16.8.
Desde entonces, toda la arquitectura de react se ha transformado en una serie de "Hooks" que permiten implementar la mayoria de los patrones de programacion mas importantes.
El useReducer es una propuesta de React para separar la logica de la vista en tus componentes. Hay otras soluciones como Redux, Flux, Global Context, etc. Sin embargo, el useReducer es sencillo de usar y mantiene un alcance local sobre los datos, es decir, a pesar de reusar las funciones y codigo de los componentes, no se compartiran los datos entre sí.
Desde entonces, toda la arquitectura de react se ha transformado en una serie de "Hooks" que permiten implementar la mayoría de los patrones de programación mas importantes.

## Ejemplo de useReducer

Este es el ejemplo más sencillo de useReducer:
El useReducer es una nueva propuesta de React para separar la logica de la vista en tus componentes. Hay otras soluciones como Redux, Flux, Global Context, etc. Sin embargo, el useReducer se ha vuelto popular por ser sencillo de usar y mantener un alcance local sobre los datos, es decir, a pesar de reutilizar las funciones y código de los componentes, no se compartirán los datos entre sí.

```react
const intitialCounter = () => ({counter: 0});
const [state, dispatch] = useReducer(counterReducer, intitialCounter());
```
> Separar los datos de los componentes ayudar a prevenir errores comunes y reutilizar la información y la lógica en la aplicación.
El hook `useReducer` recibe como primer parámetro una función que define el `reducer`, y va a retornar un arreglo de dos valores que representan al nuevo estado (`state`) y el dispatcher: El objeto que permite ejecutar las acciones/funciones de la lógica del reducer (`actions`). Como segundo parámetro se debe pasar una función que retorne un objeto con los valores iniciales del estado.

> El segundo valor del arreglo que deveulve el useReducer se llama "dispacher" y no "actions" porque es necesario tener un "despachador" de acciones como intermediario para evitar conflictos en los datos.
## Ejemplo de useReducer

A su vez la función reducer (en este ejemplo se llama `counterReducer`) se define con 2 parámetros: El `state` que contiene los datos del reducer, y un objeto `"actions"` que se usa para identificar las acciones que podemos ejecutar para manipular el state.
El primer paso es declarar una función reducer (en este ejemplo se llama `counterReducer`) se define con 2 parámetros: El `state` que contiene los datos del reducer, y un objeto `actions` que se usa para identificar las acciones que podemos ejecutar para manipular el state.

```react
```javascript
function counterReducer(state , action = {}) {
// Aquí el reducer recibe el estado actual
// luego ejecuta las acciones
// por ultimo retorna el estado nuevo
}
```

Esta función reducer se va a ejecutar en cada llamado de acción y deberá retornar una nueva versión del estado que reemplaza por completo la anterior al terminar su ejecución, por lo que hay que ser cuidadoso y sólo alterar lo que necesitamos y retornar siempre los demás valores del estado utilizando la desestructuracion (js destructuring) 🤓.
Esta función reducer se encarga de mutar (o "modificar") el estado de tu componente en función de los tipos de acciones predefinidas, y deberá retornar una nueva versión del estado que reemplaza por completo la anterior al terminar su ejecución, por lo que hay que ser cuidadoso y sólo alterar lo que necesitamos y retornar siempre los demás valores del estado utilizando la desestructuracion (js destructuring) 🤓.

👍**SI**

```javascript
return { ...state, counter: state.counter + 1 }
function counterReducer(state , action = {}) {
// Hagas lo que hagas, siempre retorna un nuevo estado

//👍**SI**
return { ...state, counter: state.counter + 1 }

//🚫**NO**
//return { counter: state.counter + 1 }
}
```

🚫**NO**
Esta función se utiliza como primer parámetro del hook `useReducer`. Como segundo parámetro se debe pasar una función que retorne un objeto con los valores iniciales del estado.

El llamado al hook retorna un arreglo de dos valores que representan al nuevo estado (`state`) y el dispatcher: El objeto que llama la ejecución de las acciones de la lógica del reducer (`actions`).

```javascript
return { counter: state.counter + 1 }
const intitialCounter = () => ({counter: 0});
const [state, dispatch] = useReducer(counterReducer, intitialCounter());
```

Dentro del reducer, el objeto `actions` contiene una propiedad `type` que nos indica que acción ha sido invocada, y podremos escribir la lógica basado en ello.
Dentro del reducer, el objeto `actions` contiene una propiedad `type` que nos indica qué acción ha sido invocada, y podremos escribir la lógica mutar el estado por completo.

```javascript
export default function counterReducer(state, action = {}) {
Expand All @@ -69,21 +71,23 @@ export default function counterReducer(state, action = {}) {
return { ...state, counter: 0 };
default:
// En caso no tener ningún tipo se retorna el estado sin alterar
return state;
throw Error("No se encuentra la acción especificada")
}
}
```

Ademas de las acciones especificadas, se coloca un caso `default` que se ejecuta cuando el tipo de acción no esta definido, para lo cual se arroja un error que interrumpe la aplicación. Esto puede parecer un poco extremo, pero es mejor tener un error visible y depurarlo, que tener una aplicación sin errores(🐞bugs) pero que no funciona como debería.

Ya con esto podemos tener tanto las funciones `counterReducer` e `intitialCounter` exportadas en un archivo, para ser utilizadas por cualquier otro componente 👌.

## Porque usar useReducer

Estamos acostumbrados a percibir los componentes como la unidad que agrupa la vista y la lógica para su funcionamiento. Por ejemplo: En el siguiente código hay un componente `Counter` que tiene el HTML para definir como debería verse un contador de números y tambien existe la logica de como deberia sumar una unidad cada vez que se presione el botón "+1"
Estamos acostumbrados a percibir los componentes como la unidad que agrupa la vista y la lógica para su funcionamiento. Por ejemplo: En el siguiente código hay un componente `Counter` que tiene el HTML para definir como debería verse un contador de números y también existe la lógica de como sumar una unidad cada vez que se presione el botón "+1"

```jsx
export default function Counter() {

// Logica ⬇️
// Lógica ⬇️
const [counter, setCounter] = useState(0);
const increment = () => setCounter(counter + 1);

Expand All @@ -102,17 +106,17 @@ export default function Counter() {

Pero ¿Qué pasa si necesitamos reutilizar sólo la lógica en otros componentes? Podríamos [hablar de estados centralizados](https://4geeks.com/es/lesson/context-api-es), pero ¿Qué pasa si sólo quiero reutilizar la lógica y que cada componente tenga un estado propio? Una solución poco práctica seria copiar y pegar, o exportar las funciones desde un archivo aparte y buscar alguna manera de hacerlas trabajar con el estado de cada componente 😰. Eso no suena conveniente...

La solución a este problema es `useReducer`, que como dice su nombre, su función es **reducir** un estado y su lógica a una unidad reutilizable, permitiendo que esta se pueda exportar desde un archivo a los componentes que lo necesiten 💪. Este reducer va a cohexistir con el resto de la sintaxis típica de un componente React, puedes [aprender más aquí](https://4geeks.com/es/lesson/making-react-components-es).
Una solución a este problema es `useReducer`, que como dice su nombre, su función es **reducir** un estado y su lógica a una unidad reutilizable, permitiendo que esta se pueda exportar desde un archivo a los componentes que lo necesiten 💪. Este reducer va a coexistir con el resto de la sintaxis típica de un componente React, puedes [aprender más aquí](https://4geeks.com/es/lesson/making-react-components-es).

## Migrando de useState a useReducer

En este ejemplo tenemos un contador que no solamente suma de 1 en 1, sino también tiene otras opciones para modificar su valor.

![react counter using state](https://breathecode.herokuapp.com/v1/media/file/state-counter-png?width=200)

Para realizar todas estas acciones se necesitan funciones para cada una de ellas, ademas del estado en si. Para eso usaremos el clasico hook `useState`, [aprende mas aquí](https://4geeks.com/es/lesson/react-hooks-explained-es).
Para realizar todas estas acciones se necesitan funciones para cada una de ellas, ademas del estado en si. Para eso usaremos el clásico hook `useState`, [aprende mas aquí](https://4geeks.com/es/lesson/react-hooks-explained-es).

```react
```jsx
export default function CounterUsingState() {
const [counter, setCounter] = useState(0);
const increment = () => setCounter(counter + 1);
Expand All @@ -139,7 +143,7 @@ export default function CounterUsingState() {

Esto funciona perfecto, pero para hacer la lógica reutilizable y moverlo a otro archivo, lo convertiremos en un reducer:

```react
```javascript
// counterReducer.js
export const intitialCounter = () => ({
counter: 0
Expand All @@ -165,7 +169,7 @@ export default function counterReducer(state, action = {}) {

Ahora desde el componente importamos y hacemos uso del reducer:

```react
```jsx
import React, { useReducer } from "react";
import counterReducer, { intitialCounter } from "./counterReducer";

Expand Down Expand Up @@ -206,6 +210,6 @@ Para que esto funcione fue necesario usar el state del reducer y reemplazar las
## Todo listo

Ya hemos visto las ventajas de useReducer y sabemos como extraer la lógica de nuestro estado a un reducer ubicado en un archivo externo que pueden reutilizar los demás componentes. Esto no significa que tengas que desechar `useState` por completo y solo usar `useReducer`, como todo en programación se trata de usar la herramienta adecuada para el trabajo adecuado. Puedes aprender más de React y las herramientas que tiene [en esta categoria](https://4geeks.com/es/technology/reactjs)
Ya hemos visto las ventajas de useReducer y sabemos como extraer la lógica de nuestro estado a un reducer ubicado en un archivo externo que pueden reutilizar los demás componentes. Esto no significa que tengas que desechar `useState` por completo y solo usar `useReducer`, como todo en programación se trata de usar la herramienta adecuada para el trabajo adecuado. Puedes aprender más de React y las herramientas que tiene [en esta categoría](https://4geeks.com/es/technology/reactjs)

Los reducer son ideales cuando tenemos muchas funciones asociadas al estado, y nos convenga agrupar lógica y datos. Esto puede darse en un escenario de gran complejidad o cuando se necesite reutilizar funciones y estados en varios componentes, ahi tendrás la poderosa herramienta de **useReducer** en tu arsenal.
Loading

0 comments on commit d94d4af

Please sign in to comment.