diff --git a/src/content/lesson/context-api.md b/src/content/lesson/context-api.md
index 91b52f77f..9720a760d 100644
--- a/src/content/lesson/context-api.md
+++ b/src/content/lesson/context-api.md
@@ -19,7 +19,7 @@ People say that React.js makes the easy stuff hard and the hard stuff easy. It's
3. [Redux](https://redux.js.org/)?? Overkill.
-### The Context API is here to solve some of those conundrums by:
+### The Context API is here to solve some of those conundrums by
1. Centralizing a global application state: Instead of being limited to local states on views, you can now share data on one central component and spread to its inner components (children, grandchildren and so forth). The centralized state is called **store**, and we can spread it by using the **Context.Provider**.
@@ -55,7 +55,7 @@ We must split the **store** from the **actions** and the **views** (components)
Ok, after a couple of hours to make the context API implementation simpler without using bindings... this is what I got in 5 simple steps!:
-- **Step 1 (Create the context)**: This step has almost no logic, just call the `createContext` function from React. That object will be shared within all the consumers during the application's lifetime, it will contain the application **store** and **actions**.
++ **Step 1 (Create the context)**: This step has almost no logic, just call the `createContext` function from React. That object will be shared within all the consumers during the application's lifetime, it will contain the application **store** and **actions**.
*AppContext.js*
@@ -67,11 +67,12 @@ import React from 'react';
const AppContext = React.createContext(null);
```
-- **Step 2 (Store and Actions)**: Create a `ContextWrapper` component which will be used to pass the context (step 1) to the Consumers. The `ContextWrapper`'s state is where we declare our initial *global state*, which includes the data (store) and the functions (actions).
++ **Step 2 (Store and Actions)**: Create a `ContextWrapper` component which will be used to pass the context (step 1) to the Consumers. The `ContextWrapper`'s state is where we declare our initial *global state*, which includes the data (store) and the functions (actions).
> Note that we have to export both `AppContext` and `ContextWrapper`.
*AppContext.js*
+
```js
// Step 2: Create a ContextWrapper component that has to be the parent of every consumer
@@ -80,22 +81,22 @@ import React, { useState } from 'react';
export const AppContext = React.createContext(null);
export const ContextWrapper = (props) => {
- const [ store, setStore ] = useState({
- todos: ["Make the bed", "Take out the trash"]
- });
- const [ actions, setActions ] = useState({
- addTask: title => setStore({ ...store, todos: store.todos.concat(title) })
- });
-
- return (
-
- {props.children}
-
- );
+ const [ store, setStore ] = useState({
+ todos: ["Make the bed", "Take out the trash"]
+ });
+ const [ actions, setActions ] = useState({
+ addTask: title => setStore({ ...store, todos: store.todos.concat(title) })
+ });
+
+ return (
+
+ {props.children}
+
+ );
}
```
-- **Step 3 (Views)**: Now your main component can be wrapped inside `ContextWrapper` so that all child components will have access to the **Context**. For this quick example, we will be using the `` component as our main component (the declaration is on the last step).
++ **Step 3 (Views)**: Now your main component can be wrapped inside `ContextWrapper` so that all child components will have access to the **Context**. For this quick example, we will be using the `` component as our main component (the declaration is on the last step).
*index.js*
@@ -109,15 +110,15 @@ import { ContextWrapper } from 'path/to/AppContext.js';
import TodoList from 'path/to/TodoList';
const MyView = () => (
-
-
-
- );
+
+
+
+ );
ReactDOM.render(, document.querySelector("#app"));
```
-- **Step 4**: Now we can create the `TodoList` component, knowing that we can use `useContext()` hook to read the store from the **global state** (no props necessary).
++ **Step 4**: Now we can create the `TodoList` component, knowing that we can use `useContext()` hook to read the store from the **global state** (no props necessary).
In this case, the component will render the to-do's and also be able to add new tasks to the list.
@@ -128,21 +129,21 @@ import React, { useContext } from 'react';
import { AppContext } from 'path/to/AppContext.js';
export const TodoList = () => {
- const context = useContext(AppContext);
- return
}
```
-Very often we will use the `useContext` hook that you see above
+Very often we will use the `useContext` hook that you see above
```javascript
const context = useContext(AppContext);
return
- {context.store.todos.map((task, i) => (
{task}
))}
-
+ {context.store.todos.map((task, i) => (
{task}
))}
+
```
@@ -151,14 +152,13 @@ In its destructured variant. Pay attention to how that also simplifies the way w
```javascript
const {store, actions} = useContext(AppContext);
return
+```javascript runable=true
+let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+////////////////////////////
+// Slice
+let halfArr = numbers.slice(0, 5)
+console.log({ halfArr })
+// Ouputs: { halfArr: [ 1, 2, 3, 4, 5 ] }
+
+////////////////////////////
+// Splice
+let middleItems = numbers.splice(4, 2)
+console.log({ middleItems })
+// Ouputs: { middleItems: [ 5, 6 ] }
+console.log({ numbers, arr })
+// Ouputs: { numbers: [ 1, 2, 3, 4, 7, 8, 9, 10 ] }
+```
> ☝️ Splice puede aceptar tantos parámetros opcionales como se quiera y estos sustituirán la parte del array que ha sido eliminada. De esta forma el primer parámetro indica el índice desde el cual empieza a borrar, el segundo parámetro cuantos elementos borrarás y del tercero en adelante los elementos que se insertan a partir de la posición que se indica en el primer parámetro.
@@ -246,6 +260,24 @@ let autos = [
console.log(autos); // --> [ {tipo: 'Saab', año: 2001}, {tipo: 'BMW', año: 2010}, {tipo: 'Volvo', año: 2016} ]
```
-
-
-
> ☝ Splice can accept as many optional parameters as wanted and those will substitute the part of the array that has been deleted. The first parameter is the index where the deletion starts, the second is how many elements will be deleted, and from the third onward, the elements inserted after the position set by the first parameter.
@@ -244,6 +259,26 @@ let cars = [
console.log(cars); // --> [ {type: 'Saab', year: 2001}, {type: 'BMW', year: 2010}, {type: 'Volvo', year: 2016} ]
```
-
+Here's a runing example of all the above
+
+```javascript runable=true
+// Sorting strings
+let fruits = ["Banana", "Orange", "Apple", "Mango"];
+fruits.sort();
+console.log(fruits); // --> ['Apple', 'Banana', 'Mango', 'Orange']
+fruits.reverse();
+console.log(fruits); // --> ['Orange', 'Mango', 'Banana', 'Apple']
+
+// Sorting numbers
+let points = [40, 100, 1, 5, 25, 10];
+points.sort(function(a, b) { return a - b });
+console.log(points); // --> [1, 5, 10, 25, 40, 100]
-
+// Sorting objects
+let cars = [
+ { type: "Volvo", year: 2016 },
+ { type: "Saab", year: 2001 },
+ { type: "BMW", year: 2010 }];
+cars.sort(function(a, b) { return a.year - b.year });
+console.log(cars); // --> [ {type: 'Saab', year: 2001}, {type: 'BMW', year: 2010}, {type: 'Volvo', year: 2016} ]
+```
\ No newline at end of file
diff --git a/src/content/lesson/what-is-react-flux.es.md b/src/content/lesson/what-is-react-flux.es.md
index 4619a9861..43c80d8bf 100644
--- a/src/content/lesson/what-is-react-flux.es.md
+++ b/src/content/lesson/what-is-react-flux.es.md
@@ -27,7 +27,7 @@ Aquí hay una lista de todas las ventajas de usarlo:
![React Flux](https://github.com/breatheco-de/content/blob/master/src/assets/images/aa1a5994-8de9-4d24-99ce-3a0d686c30bd.png?raw=true)
-### Flux divide la aplicación en 3 capas:
+### Flux divide la aplicación en 3 capas
| | |
|:-----------|:----------------|
@@ -37,101 +37,208 @@ Vistas/Views (Components) |Cada componente React que llama a cualquier acci
## Construyendo nuestra primera historia de usuario con Flux
-El siguiente proyecto es una aplicación de To-Do List (lista de tareas) con 2 historias de usuario principales:
+El siguiente proyecto es una aplicación de To-Do List (lista de tareas) con 3 historias de usuario principales:
-+ Crear tarea (ya desarrollada y en funcionamiento).
++ Crear tarea.
++ Mostrar la lista de tareas
+ Eliminar tarea.
-Para codificar la función para eliminar tareas, tenemos que actualizar estos archivos: (1) El Componente (para cuando el usuario haga clic), (2) las Acciones, (3) El Store (dos veces), y (4) el Componente una última vez. Son solo 3 archivos y 5 actualizaciones. Y tienes que hacer eso para cada historia de usuario que vayas a construir en tu aplicación.
+Para codificar esta lista de tareas tenemos que crear 4 archivos:
+
+1. Un componente para agregar tarea.
+3. Un componente para los items de la lista.
+2. Un archivo para las actions y el estado(store).
+4. El archivo principal donde integraremos todo.
> *Al final, trabajar con Flux tiene que convertirse en algo tan automático como andar en bicicleta.*
![react flux](https://github.com/breatheco-de/content/blob/master/src/assets/images/77c93bfa-92cb-44e3-a7c5-c959e27c5ccc.jpeg?raw=true)
-## Vamos a implementar la función eliminar tarea
+## Vamos a implementar una lista de tareas
-### 1) ¿Qué acción del usuario inicia la función?
+### 1) Crearemos un reducer para implementar el patrón flux
-(Siempre es un evento típico de JS como: hacer clic, on hover, cambiar el tamaño, etc.)
+Para poder tomar el control del flujo de los datos en nuestra aplicación utilizaremos un `reducer` para agrupar las funciones y la lógica de la aplicación (actions) junto con los datos que manejan y que tienen que estar disponible para los componentes (state).
-***Todo comienza cuando el usuario haga clic en el icono de la papelera. Es por eso que necesitamos iniciar nuestra aplicación escuchando el típico evento onClick en el botón de eliminar.***
+Por ahora solo diremos que el reducer es una función que genera un estado nuevo cada vez que se ejecuta y lo que haga dependerá de la información que reciba en la función `action`. Esto nos permitirá llamar a las `actions` para actualizar el estado como lo indica el patrón flux. Para entender en detalle como funciona un reducer, puedes [leer esté artículo]() donde lo explicamos a profundidad.
```javascript
-// En el componente que representa cada elemento de tarea, debemos agregar un botón y también un activador onClick que llame
-// a la respectiva función TodoAction.deleteTodo(task) que crearemos en las acciones:
-
-
+// Esta es la función reducer
+const TaskReducer = (state, action) => {
+ // Dependiendo del type de la acción realiza una tarea distinta
+ switch (action.type) {
+ case "add":
+ return [...state, action.payload];
+ case "remove":
+ let newState=[...state]
+ newState.splice(action.index, 1);
+ return newState
+ default:
+ return state;
+ }
+};
```
-### 2) Luego necesitamos codificar nuestra acción dentro del archivo MyActions.js de esta forma:
+El siguiente paso es hacer que esta función esté disponible para todos los componentes de mi aplicación, para eso utilizaremos un contexto con el hook `useReducer`, el cual nos va a permitir crear el estado y la función `actions` para ponerla a disposición del resto de la aplicación.
-```javascript
-MyActions.js
-
-// En este caso, decidimos que esta función (conocida como action) recibirá el ID de la tarea que se eliminará
-class MyActions extends Flux.Actions{
- deleteTask(taskToDelete){
- // Obtiene la lista actual de acciones del store
- let currentActions = MyStore.getActions();
- let updatedActions = currentActions.filter((task) => {
- return (task.id != taskToDelete.id);
- });
-
- this.dispatch('MyStore.setActions', updatedActions);
- }
+```react
+//TaskContext.jsx
+import { useReducer, createContext } from "react";
+
+// Creamos el contexto vacío
+const TaskContext = createContext(null);
+
+const TaskReducer = (state, action) => {
+ // Aquí va el reducer que se definió anteriormente👆
+};
+
+// Crearemos un componente que va a envolver nuestra aplicación en el contexto
+export function TaskProvider({ children }) {
+ // Creamos el state 'tasks' y el despachador 'taskActions'
+ // adicionalmente pasamos como estado inicial un arreglo vacío
+ const [tasks, taskActions ]= useReducer(TaskReducer, []);
+ return (
+ {/* Creamos el contexto con nuestro state y actions */}
+ {children}
+ );
}
+
+// Es necesario exportar el contexto para usarlo en otros componentes
+export default TaskContext;
```
-> ☝ Este es un componente de clase. Te recomendamos que uses componentes funcionales y hooks en su lugar, ya que los componentes de clase están considerados como legacy (deprecados).
+Ya con esto tenemos listo nuestro contexto con las tasks, ahora solo falta envolver nuestra aplicación en este componente para empezar a utilizarlo.
-### 3) Actualizar el store para manejar la nueva acción enviada
+```react
+//index.jsx
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import { TaskProvider } from "./TaskContext.jsx";
+
+ReactDOM.createRoot(document.getElementById("root")).render(
+
+
+
+
+ ,
+);
-```javascript
-// Dentro de todoStore tenemos un método HandleActions que contiene la lógica para manejar cada acción distribuida
-// Tenemos que agregar un nuevo caso al switch con el nombre 'DELETE_TODO'
-// Tiene que coincidir con el nombre de la acción que se envió
-
-handleActions(action) {
- switch (action.type) {
- ...
- case 'DELETE_TODO': {
- this.deleteTodo(action.id);
- break;
- }
- }
-}
```
+Ahora solo queda llamar al contexto desde los componentes que necesiten hacer uso de nuestras tareas.
-### 4) Dentro del To-Do Store, implementa la lógica para eliminar la tarea y emitir los cambios
+### 2) Empecemos por agregar una nueva tarea
-```javascript
+Para ello usaremos un componente que muestre una caja de texto y un botón que realiza la acción de agregar la tarea, todo dentro de un formulario para facilitar el manejo del evento de envío(submit).
+
+Todo esto es básico de un formulario en react, pero como queremos utilizar las `actions` del contexto, necesitamos llamarlo en el componente.
-// En cualquier lugar de tu clase TodoStore, agrega un nuevo método que finalmente elimine la tarea del to-do list
-// En este caso estamos usando la función de filter porque devuelve el mismo array pero solo con
-// los elementos que coinciden con la pregunta lógica dentro del filtro (task.id != id)
-
-class TodoStore extends EventEmitter {
- ...
- deleteTodo(id){
- this.todos = this.todos.filter((task)=>{
- // Filtra todas las tareas que tienen el id dado
- return (task.id != id);
- });
- this.emit('change');
+```react
+import { tasks, useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
+
+export default function AddItem() {
+ const { taskActions } = useContext(TaskContext);
+ // A partir de este punto tenemos disponibles las actions del reducer
+ // ...
+}
+```
+
+Para hacer uso de estas `actions` se llama a la función y se le pasa como parámetro un objeto con la propiedades de la acción que queremos realizar, siendo la mas importante `type` que indica la acción especifica a ejecutar. El resto de las propiedades son datos opcionales que pueden ser requeridos por la acción.
+
+```react
+// AddItem.jsx
+import { useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
+
+export default function AddItem() {
+ // Hacemos uso del contexto y accedemos a la función 'taskActions'
+ const { taskActions } = useContext(TaskContext);
+ function handleAddTask(e) {
+ e.preventDefault();
+ // Llamamos al actions especificándole 'type'
+ // asi como también la tarea que se va a agregar
+ let textbox = e.target.elements.task;
+ taskActions({ type: "add", payload: textbox.value });
+ textbox.value = "";
}
- ...
+ return (
+
+
+
+ );
}
```
-> ☝ Este es un componente de clase. Te recomendamos que uses componentes funcionales y hooks en su lugar, ya que los componentes de clase están considerados como legacy (deprecados).
+### 3) Ahora vamos a mostrar la lista
+
+De la misma forma como accedemos a `taskActions`, también podemos acceder al objeto `tasks` que contiene el estado con la lista. Igual que antes, debemos hacer uso de `useContext` en nuestro componente.
+
+```react
+import { useContext } from "react";
+import "./App.css";
+import TaskContext from "./TaskContext.jsx";
+import ListItem from "./ListItem.jsx";
+import AddItem from "./AddItem.jsx";
+
+export default function App() {
+ // Accedemos al contexto, pero esta vez solo vamos a usar 'tasks'
+ const {tasks} = useContext(TaskContext);
+
+ return (
+
+
Todo list
+
+
+ {tasks.map((task, index) => (
+
+ ))}
+
+
+ );
+}
+```
+
+Puedes notar que aparece el componente `AddItem` que vimos previamente y desde donde se pueden agregar tarea. Luego de eso se hace el renderizado de la lista con la función `map`, pero notamos que se esta usando un componente `ListItem` para mostrar los elementos, no solo eso sino que ahi también corresponde hacer la eliminación de la tarea, veamos ese componente.
+
+### 4) Eliminación de items
-## El Resultado
+Si bien el renderizado es básico (un elemento `li` con el texto y un botón), lo interesante es como hacemos la eliminación del item con las actions.
-Finalmente, tenemos una nueva función implementada en nuestro proyecto. Para seguir agregando más funciones, solo tienes que iniciar de nuevo el flujo de trabajo de codificación de Flux desde el paso 1.
+***Todo comienza cuando el usuario haga clic en el icono de la papelera. Es por eso que necesitamos iniciar nuestra aplicación escuchando el típico evento onClick en el botón de eliminar.***
-
+```react
+ onClick={() => taskActions({ type: "remove", index })}
+```
-
+Notamos que el llamado al action es parecido al que usamos para agregar items, pero se le esta pasando un parámetro distinto llamado `index`, que le indica al dispatcher que elemento va a eliminar. Asi como vimos en ambos ejemplos, podemos pasar la data que necesite nuestra action al momento de llamarla como parámetros adicionales.
+
+```react
+import { useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
+
+export default function ListItem({ task, index }) {
+ const { taskActions } = useContext(TaskContext);
+
+ return (
+
+ {task}
+
+
+ );
+}
+````
+## Resultado final
+Ya hemos implementado la lógica de nuestra aplicación en un contexto aplicando el patrón flux, permitiendo su uso en distintos componentes. A continuación podemos ver el resultado final.
+
diff --git a/src/content/lesson/what-is-react-flux.md b/src/content/lesson/what-is-react-flux.md
index 397b43072..5e9fca9da 100644
--- a/src/content/lesson/what-is-react-flux.md
+++ b/src/content/lesson/what-is-react-flux.md
@@ -32,106 +32,194 @@ Here is a list of all the advantages of using it:
| | |
|:-----------|:----------------|
Views (Components) |Every React Component that calls any Flux action is called a view. The reason to call those components differently is that React components are supposed to communicate with each other through their props (without Flux).
Once a React Component is hard-coded to Flux, you will not be able to reuse that component in the future (on this or any other development). |
-|Actions |Actions can be triggered components (when the user clicks or interacts with the application) or by the system (for example, the auto-save functionality). Actions are the first step of any Flux workflow, and they always need to dispatch to the store. |
+|Actions |Actions can be triggered by components (when the user clicks or interacts with the application) or by the system (for example, the auto-save functionality). Actions are the first step of any Flux workflow, and they always need to dispatch the store. |
|Store |The store contains all the application data. It handles everything incoming from the dispatcher and determines the way data should be stored and retrieved. |
-## Building our first User History with Flux
+## Building a to-do list with flux.
-The following project is a To-Do List application with 2 main user stories:
+### 1) Let's build a reducer that implements the flux pattern.
-+ Create task (already developed and working).
-+ Delete task.
+To take control over the flow of the data in our application we'll use a `reducer` to group the functions and the logic of the application (actions) along with the data that they handle and must be available to all the other components (state).
-To code the delete functionality, we have to update these files: (1) The Component (for when the user clicks on the track), (2) The Actions, (3) The Store (two times), and (4) The Component one last time. It's only 3 files and 5 updates. And you have to do that for every user story that you are going to build into your application.
+For now, let's just say that the reducer is a function that generates a new state every time it runs, and what it does depends on the information passed to the `action` function. This allows us to call the `actions` to update the state as indicates the flux pattern. To understand better how a reducer works, you can read [this article]() where we cover this in more depth.
-> *In the end, working with Flux has to become something as automatic as riding a bike.*
-
-![react flux](https://github.com/breatheco-de/content/blob/master/src/assets/images/77c93bfa-92cb-44e3-a7c5-c959e27c5ccc.jpeg?raw=true)
+```javascript
+// This is the reducer function
+const TaskReducer = (state, action) => {
+ // Depending on the action type, it performs a specific action
+ switch (action.type) {
+ case "add":
+ return [...state, action.payload];
+ case "remove":
+ let newState=[...state]
+ newState.splice(action.index, 1);
+ return newState
+ default:
+ return state;
+ }
+};
+```
-## Let's Implement the Delete Task Functionality
+The next step is to make this function available for all the other components of the application, for that we'll use a context with the hook `useReducer`, which will allow us to create a state and the `actions` function to publish it to the rest of the components.
-### 1) What user action starts the functionality?
+```jsx
+//TaskContext.jsx
+import { useReducer, createContext } from "react";
-(It’s always a typical JS event like click, hover, resize, etc.)
+// Create an empty context
+const TaskContext = createContext(null);
-***Everything starts whenever the user clicks on the trash can icon. That is why we need to start our application by listening to the typical onClick event on the delete button.***
+const TaskReducer = (state, action) => {
+ // Here is the reducer defined previously👆
+};
-```javascript
-// In the component that renders each to-do item we need to add a button and also an onClick listener that calls
-// the respective TodoAction.deleteTodo(task) function that we will create on the actions:
+// Create a component to wrap our application within the context
+export function TaskProvider({ children }) {
+ // Create the state 'tasks' and the dispatcher 'taskActions'
+ // additionally we'll pass an empty array as an initial value.
+ const [tasks, taskActions ]= useReducer(TaskReducer, []);
+ return (
+ {/* Create the context with our state and actions */}
+ {children}
+ );
+}
-
+// Is necessary to export the context for it to be used in other components.
+export default TaskContext;
```
-### 2) Then we need to code our action inside the MyActions.js file like this:
+Now the context is ready with our tasks, all we have to do is wrap our app with this component to start using our context.
+
+```react
+//index.jsx
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import { TaskProvider } from "./TaskContext.jsx";
+
+ReactDOM.createRoot(document.getElementById("root")).render(
+
+
+
+
+ ,
+);
-```javascript
-MyActions.js
-
-// In this case, we decided that this function (a.k.a action) will receive the ID of the task to be deleted.
-class MyActions extends Flux.Actions{
- deleteTask(taskToDelete){
- // Get the current list of actions from the store
- let currentActions = MyStore.getActions();
- let updatedActions = currentActions.filter((task) => {
- return (task.id != taskToDelete.id);
- });
-
- this.dispatch('MyStore.setActions', updatedActions);
- }
-}
```
+The only thing left to do is to call the context in the components that need to use our tasks.
-> ☝ This is a class component. We strongly recommend you to use functional components and hooks instead because class components are legacy.
+### 2) Let's start adding a new task
-### 3) Update the store to handle that new dispatched action
+For that, we'll use a component that shows a textbox and a button that dispatches the adding action, all inside a form to ease the handle of the submit event.
-```javascript
-// Inside the todoStore we have a HandleActions method that contains the logic to handle each dispatched action
-// We have to add a new case to the switch with the name 'DELETE_TODO'
-// It has to match the name of the action that was dispatched
-
-handleActions(action) {
- switch (action.type) {
- ...
- case 'DELETE_TODO': {
- this.deleteTodo(action.id);
- break;
- }
- }
-}
-```
+All that is basic stuff, but since we want to use the context `actions`, we need to call it from within the component.
-### 4) Inside the To-Do Store, implement the actual logic for deleting the task and emitting the changes
+```react
+import { tasks, useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
-```javascript
+export default function AddItem() {
+ const { taskActions } = useContext(TaskContext);
+ // From this point onwards we have the reducer's actions available.
+ // ...
+}
+```
-// Anywhere on your TodoStore class, add a new method that finally deletes the task from the todo list.
-// In this case we are using the filter function because it returns the same array but only with
-// the elements that match the logical question inside the filter (task.id != id)
-
-class TodoStore extends EventEmitter {
- ...
- deleteTodo(id){
- this.todos = this.todos.filter((task)=>{
- // Filter all tasks that have the given id
- return (task.id != id);
- });
- this.emit('change');
+To make use of these `actions` we call the function passing as a parameter an object with the properties of the action we want to call, being the most important the property `type` that indicates the specific action to execute. The rest of the properties are optional data that may be required by the action itself.
+
+```react
+// AddItem.jsx
+import { useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
+
+export default function AddItem() {
+ // Using the context we access the 'taskActions' function.
+ const { taskActions } = useContext(TaskContext);
+ function handleAddTask(e) {
+ e.preventDefault();
+ // Calling the action specifying the 'type'
+ // as well as task data that will be added.
+ let textbox = e.target.elements.task;
+ taskActions({ type: "add", payload: textbox.value });
+ textbox.value = "";
}
- ...
+ return (
+
+
+
+ );
}
```
-> ☝ This is a class component. We strongly recommend you to use functional components and hooks instead because class components are legacy.
+### 3) Now let's show the list
+
+In the same manner that we access `taskActions`, we can also access the `tasks` object that contains the state of the list. Just like before, we must use the `useContext` hook in our component.
+
+```react
+import { useContext } from "react";
+import "./App.css";
+import TaskContext from "./TaskContext.jsx";
+import ListItem from "./ListItem.jsx";
+import AddItem from "./AddItem.jsx";
+
+export default function App() {
+ // Accessing the context, but this time only using 'tasks'
+ const {tasks} = useContext(TaskContext);
+
+ return (
+
+
Todo list
+
+
+ {tasks.map((task, index) => (
+
+ ))}
+
+
+ );
+}
+```
+
+You can see that we are using the `AddItem` component where you can add a task. After that is being rendered the list with a `map` function, but a component `ListItem` is being used to show this element, and it also has the functionality to remove a task, let's check out that component.
-## The Result
+### 4) Task deletion
-Finally, we have a new functionality implemented into our project. To keep adding more functionalities, you just have to start the Flux coding workflow from step 1 all over again.
+Even though the render is very basic (a `li` element with the text and a button), what's interesting is how we delete an item with the actions.
-
+***I all stats with the user clicking the trash can icon. That's why we need to start our component by listening to the classic onClick event on the delete button,***
-
+```react
+ onClick={() => taskActions({ type: "remove", index })}
+```
+
+We notice that the call to `actions` is similar to the one used to add items, but in this case is receiving a different parameter called `index`, which indicates to the dispatcher which elements are going to be deleted. Just like we saw in both examples, we can pass any data that's needed to the action at the moment of calling it, as additional parameters.
+
+```react
+import { useContext } from "react";
+import TaskContext from "./TaskContext.jsx";
+
+export default function ListItem({ task, index }) {
+ const { taskActions } = useContext(TaskContext);
+
+ return (
+
+ {task}
+
+
+ );
+}
+````
+## Final result
+We have implemented the logic of our application in a context applying the flux pattern, allowing its use in different components. Now we can see the final result working.
+